diff options
1134 files changed, 13931 insertions, 8777 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 5e54ceea3d7..83b92b7fa09 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -64,6 +64,10 @@ jobs: - name: cargo update # Remove first line that always just says "Updating crates.io index" run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log + - name: cargo update library + run: | + echo -e "\nlibrary dependencies:" >> cargo_update.log + cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log - name: cargo update rustbook run: | echo -e "\nrustbook dependencies:" >> cargo_update.log @@ -74,6 +78,7 @@ jobs: name: Cargo-lock path: | Cargo.lock + library/Cargo.lock src/tools/rustbook/Cargo.lock retention-days: 1 - name: upload cargo-update log artifact for use in PR @@ -119,7 +124,7 @@ jobs: git config user.name github-actions git config user.email github-actions@github.com git switch --force-create cargo_update - git add ./Cargo.lock ./src/tools/rustbook/Cargo.lock + git add ./Cargo.lock ./library/Cargo.lock ./src/tools/rustbook/Cargo.lock git commit --no-verify --file=commit.txt - name: push diff --git a/.gitignore b/.gitignore index a36cb51de33..2e6499081a6 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,9 @@ build/ /src/tools/x/target # Created by default with `src/ci/docker/run.sh` /obj/ -/rustc-ice* + +## ICE reports +rustc-ice-*.txt ## Temporary files *~ diff --git a/Cargo.lock b/Cargo.lock index a18219b5683..6ea4cd8f5ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "ar_archive_writer" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de11a9d32db3327f981143bdf699ade4d637c6887b13b97e6e91a9154666963c" +checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4" dependencies = [ "object 0.36.3", ] @@ -410,12 +410,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.1.13" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" -dependencies = [ - "shlex", -] +checksum = "5208975e568d83b6b05cc0a063c8e7e9acc2b43bee6da15616a5b73e109d7437" [[package]] name = "cfg-if" @@ -539,6 +536,7 @@ name = "clippy" version = "0.1.82" dependencies = [ "anstream", + "cargo_metadata 0.18.1", "clippy_config", "clippy_lints", "clippy_utils", @@ -552,6 +550,7 @@ dependencies = [ "regex", "rustc_tools_util", "serde", + "serde_json", "syn 2.0.75", "tempfile", "termize", @@ -566,7 +565,6 @@ name = "clippy_config" version = "0.1.82" dependencies = [ "itertools", - "rustc-semver", "serde", "toml 0.7.8", "walkdir", @@ -598,7 +596,6 @@ dependencies = [ "quine-mc_cluskey", "regex", "regex-syntax 0.8.4", - "rustc-semver", "semver", "serde", "serde_json", @@ -617,7 +614,6 @@ dependencies = [ "arrayvec", "clippy_config", "itertools", - "rustc-semver", "rustc_apfloat", ] @@ -2230,9 +2226,12 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282" +checksum = "9aa3f302fe0f8de065d4a2d1ed64f60204623cac58b80cd3c2a83a25d5a7d437" +dependencies = [ + "clap", +] [[package]] name = "minimal-lexical" @@ -3129,6 +3128,7 @@ dependencies = [ "bstr", "build_helper", "gimli 0.31.0", + "libc", "object 0.36.3", "regex", "serde_json", @@ -3202,12 +3202,6 @@ dependencies = [ ] [[package]] -name = "rustc-semver" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84" - -[[package]] name = "rustc-stable-hash" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4542,6 +4536,7 @@ dependencies = [ "bitflags 2.6.0", "derive-where", "indexmap", + "rustc-hash", "rustc_ast_ir", "rustc_data_structures", "rustc_index", diff --git a/RELEASES.md b/RELEASES.md index 2c91ddf7826..5e4827be4ec 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -143,6 +143,8 @@ Compatibility Notes - [Turn `proc_macro_back_compat` lint into a hard error.](https://github.com/rust-lang/rust/pull/125596/) - [Detect unused structs even when implementing private traits](https://github.com/rust-lang/rust/pull/122382/) - [`std::sync::ReentrantLockGuard<T>` is no longer `Sync` if `T: !Sync`](https://github.com/rust-lang/rust/pull/125527) which means [`std::io::StdoutLock` and `std::io::StderrLock` are no longer Sync](https://github.com/rust-lang/rust/issues/127340) +- [Type inference will fail in some cases due to new implementations of `FromIterator for Box<str>`.](https://github.com/rust-lang/rust/pull/99969/) + Notably, this breaks versions of the `time` crate before 0.3.35, due to no longer inferring the implementation for `Box<[_]>`. <a id="1.80-Internal-Changes"></a> diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3dc548c4554..df29b3d54f0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -3,6 +3,7 @@ #![cfg_attr(feature = "nightly", doc(rust_logo))] #![cfg_attr(feature = "nightly", feature(rustdoc_internals))] #![cfg_attr(feature = "nightly", feature(step_trait))] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::fmt; @@ -1699,7 +1700,9 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> { /// Checks if these two `Layout` are equal enough to be considered "the same for all function /// call ABIs". Note however that real ABIs depend on more details that are not reflected in the - /// `Layout`; the `PassMode` need to be compared as well. + /// `Layout`; the `PassMode` need to be compared as well. Also note that we assume + /// aggregates are passed via `PassMode::Indirect` or `PassMode::Cast`; more strict + /// checks would otherwise be required. pub fn eq_abi(&self, other: &Self) -> bool { // The one thing that we are not capturing here is that for unsized types, the metadata must // also have the same ABI, and moreover that the same metadata leads to the same size. The diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f5f01348e46..84933540147 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -25,6 +25,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(strict_provenance)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index 9eaa292e989..bfde8abd589 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -32,7 +32,7 @@ impl<T> TypedArena<T> { } #[test] -pub fn test_unused() { +fn test_unused() { let arena: TypedArena<Point> = TypedArena::default(); assert!(arena.chunks.borrow().is_empty()); } @@ -75,7 +75,7 @@ fn test_arena_alloc_nested() { } #[test] -pub fn test_copy() { +fn test_copy() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -87,13 +87,13 @@ pub fn test_copy() { } #[bench] -pub fn bench_copy(b: &mut Bencher) { +fn bench_copy(b: &mut Bencher) { let arena = TypedArena::default(); b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 })) } #[bench] -pub fn bench_copy_nonarena(b: &mut Bencher) { +fn bench_copy_nonarena(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(Point { x: 1, y: 2, z: 3 }); }) @@ -106,7 +106,7 @@ struct Noncopy { } #[test] -pub fn test_noncopy() { +fn test_noncopy() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -118,7 +118,7 @@ pub fn test_noncopy() { } #[test] -pub fn test_typed_arena_zero_sized() { +fn test_typed_arena_zero_sized() { let arena = TypedArena::default(); #[cfg(not(miri))] const N: usize = 100000; @@ -130,7 +130,7 @@ pub fn test_typed_arena_zero_sized() { } #[test] -pub fn test_typed_arena_clear() { +fn test_typed_arena_clear() { let mut arena = TypedArena::default(); for _ in 0..10 { arena.clear(); @@ -145,7 +145,7 @@ pub fn test_typed_arena_clear() { } #[bench] -pub fn bench_typed_arena_clear(b: &mut Bencher) { +fn bench_typed_arena_clear(b: &mut Bencher) { let mut arena = TypedArena::default(); b.iter(|| { arena.alloc(Point { x: 1, y: 2, z: 3 }); @@ -154,7 +154,7 @@ pub fn bench_typed_arena_clear(b: &mut Bencher) { } #[bench] -pub fn bench_typed_arena_clear_100(b: &mut Bencher) { +fn bench_typed_arena_clear_100(b: &mut Bencher) { let mut arena = TypedArena::default(); b.iter(|| { for _ in 0..100 { @@ -230,7 +230,7 @@ fn test_typed_arena_drop_small_count() { } #[bench] -pub fn bench_noncopy(b: &mut Bencher) { +fn bench_noncopy(b: &mut Bencher) { let arena = TypedArena::default(); b.iter(|| { arena.alloc(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }) @@ -238,7 +238,7 @@ pub fn bench_noncopy(b: &mut Bencher) { } #[bench] -pub fn bench_noncopy_nonarena(b: &mut Bencher) { +fn bench_noncopy_nonarena(b: &mut Bencher) { b.iter(|| { let _: Box<_> = Box::new(Noncopy { string: "hello world".to_string(), array: vec![1, 2, 3, 4, 5] }); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a44ed828504..85d38a0e28b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2902,6 +2902,17 @@ pub struct AttrItem { pub tokens: Option<LazyAttrTokenStream>, } +impl AttrItem { + pub fn is_valid_for_outer_style(&self) -> bool { + self.path == sym::cfg_attr + || self.path == sym::cfg + || self.path == sym::forbid + || self.path == sym::warn + || self.path == sym::allow + || self.path == sym::deny + } +} + /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 27e9f3d137f..7730d0b4b78 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod util { diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 1d0c76f6cea..eeed5d36151 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -2,6 +2,7 @@ #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[cfg(feature = "nightly")] diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 51cbe808a3a..e077c544965 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -220,7 +220,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !expr.is_potential_trivial_const_arg() { + if !self.tcx.features().const_arg_path + || !expr.is_potential_trivial_const_arg() + { self.create_def( parent_def_id, node_id, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 9c073130827..80077348204 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -51,7 +51,7 @@ use rustc_span::Span; use rustc_target::spec::abi; use {rustc_ast as ast, rustc_hir as hir}; -use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; +use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; use crate::{ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { @@ -323,7 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation.path.span, ast_segment, ParamMode::Optional, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 8237bfd6792..6b39c2d3955 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(ast_lowering_generic_type_with_parentheses, code = E0214)] -pub struct GenericTypeWithParentheses { +pub(crate) struct GenericTypeWithParentheses { #[primary_span] #[label] pub span: Span, @@ -16,7 +16,7 @@ pub struct GenericTypeWithParentheses { #[derive(Subdiagnostic)] #[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")] -pub struct UseAngleBrackets { +pub(crate) struct UseAngleBrackets { #[suggestion_part(code = "<")] pub open_param: Span, #[suggestion_part(code = ">")] @@ -26,7 +26,7 @@ pub struct UseAngleBrackets { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_abi, code = E0703)] #[note] -pub struct InvalidAbi { +pub(crate) struct InvalidAbi { #[primary_span] #[label] pub span: Span, @@ -38,7 +38,7 @@ pub struct InvalidAbi { pub suggestion: Option<InvalidAbiSuggestion>, } -pub struct InvalidAbiReason(pub &'static str); +pub(crate) struct InvalidAbiReason(pub &'static str); impl Subdiagnostic for InvalidAbiReason { fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( @@ -57,7 +57,7 @@ impl Subdiagnostic for InvalidAbiReason { code = "{suggestion}", applicability = "maybe-incorrect" )] -pub struct InvalidAbiSuggestion { +pub(crate) struct InvalidAbiSuggestion { #[primary_span] pub span: Span, pub suggestion: String, @@ -65,7 +65,7 @@ pub struct InvalidAbiSuggestion { #[derive(Diagnostic)] #[diag(ast_lowering_assoc_ty_parentheses)] -pub struct AssocTyParentheses { +pub(crate) struct AssocTyParentheses { #[primary_span] pub span: Span, #[subdiagnostic] @@ -73,7 +73,7 @@ pub struct AssocTyParentheses { } #[derive(Subdiagnostic)] -pub enum AssocTyParenthesesSub { +pub(crate) enum AssocTyParenthesesSub { #[multipart_suggestion(ast_lowering_remove_parentheses)] Empty { #[suggestion_part(code = "")] @@ -91,7 +91,7 @@ pub enum AssocTyParenthesesSub { #[derive(Diagnostic)] #[diag(ast_lowering_misplaced_impl_trait, code = E0562)] #[note] -pub struct MisplacedImplTrait<'a> { +pub(crate) struct MisplacedImplTrait<'a> { #[primary_span] pub span: Span, pub position: DiagArgFromDisplay<'a>, @@ -99,7 +99,7 @@ pub struct MisplacedImplTrait<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_assoc_ty_binding_in_dyn)] -pub struct MisplacedAssocTyBinding { +pub(crate) struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, #[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")] @@ -108,7 +108,7 @@ pub struct MisplacedAssocTyBinding { #[derive(Diagnostic)] #[diag(ast_lowering_underscore_expr_lhs_assign)] -pub struct UnderscoreExprLhsAssign { +pub(crate) struct UnderscoreExprLhsAssign { #[primary_span] #[label] pub span: Span, @@ -116,7 +116,7 @@ pub struct UnderscoreExprLhsAssign { #[derive(Diagnostic)] #[diag(ast_lowering_base_expression_double_dot, code = E0797)] -pub struct BaseExpressionDoubleDot { +pub(crate) struct BaseExpressionDoubleDot { #[primary_span] #[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")] pub span: Span, @@ -124,7 +124,7 @@ pub struct BaseExpressionDoubleDot { #[derive(Diagnostic)] #[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)] -pub struct AwaitOnlyInAsyncFnAndBlocks { +pub(crate) struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] #[label] pub await_kw_span: Span, @@ -134,21 +134,21 @@ pub struct AwaitOnlyInAsyncFnAndBlocks { #[derive(Diagnostic)] #[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)] -pub struct CoroutineTooManyParameters { +pub(crate) struct CoroutineTooManyParameters { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_closure_cannot_be_static, code = E0697)] -pub struct ClosureCannotBeStatic { +pub(crate) struct ClosureCannotBeStatic { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_functional_record_update_destructuring_assignment)] -pub struct FunctionalRecordUpdateDestructuringAssignment { +pub(crate) struct FunctionalRecordUpdateDestructuringAssignment { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -156,28 +156,28 @@ pub struct FunctionalRecordUpdateDestructuringAssignment { #[derive(Diagnostic)] #[diag(ast_lowering_async_coroutines_not_supported, code = E0727)] -pub struct AsyncCoroutinesNotSupported { +pub(crate) struct AsyncCoroutinesNotSupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)] -pub struct InlineAsmUnsupportedTarget { +pub(crate) struct InlineAsmUnsupportedTarget { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_att_syntax_only_x86)] -pub struct AttSyntaxOnlyX86 { +pub(crate) struct AttSyntaxOnlyX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_abi_specified_multiple_times)] -pub struct AbiSpecifiedMultipleTimes { +pub(crate) struct AbiSpecifiedMultipleTimes { #[primary_span] pub abi_span: Span, pub prev_name: Symbol, @@ -189,7 +189,7 @@ pub struct AbiSpecifiedMultipleTimes { #[derive(Diagnostic)] #[diag(ast_lowering_clobber_abi_not_supported)] -pub struct ClobberAbiNotSupported { +pub(crate) struct ClobberAbiNotSupported { #[primary_span] pub abi_span: Span, } @@ -197,7 +197,7 @@ pub struct ClobberAbiNotSupported { #[derive(Diagnostic)] #[note] #[diag(ast_lowering_invalid_abi_clobber_abi)] -pub struct InvalidAbiClobberAbi { +pub(crate) struct InvalidAbiClobberAbi { #[primary_span] pub abi_span: Span, pub supported_abis: String, @@ -205,7 +205,7 @@ pub struct InvalidAbiClobberAbi { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_register)] -pub struct InvalidRegister<'a> { +pub(crate) struct InvalidRegister<'a> { #[primary_span] pub op_span: Span, pub reg: Symbol, @@ -214,7 +214,7 @@ pub struct InvalidRegister<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_register_class)] -pub struct InvalidRegisterClass<'a> { +pub(crate) struct InvalidRegisterClass<'a> { #[primary_span] pub op_span: Span, pub reg_class: Symbol, @@ -223,7 +223,7 @@ pub struct InvalidRegisterClass<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_reg_class)] -pub struct InvalidAsmTemplateModifierRegClass { +pub(crate) struct InvalidAsmTemplateModifierRegClass { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -234,7 +234,7 @@ pub struct InvalidAsmTemplateModifierRegClass { } #[derive(Subdiagnostic)] -pub enum InvalidAsmTemplateModifierRegClassSub { +pub(crate) enum InvalidAsmTemplateModifierRegClassSub { #[note(ast_lowering_support_modifiers)] SupportModifier { class_name: Symbol, modifiers: String }, #[note(ast_lowering_does_not_support_modifiers)] @@ -243,7 +243,7 @@ pub enum InvalidAsmTemplateModifierRegClassSub { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_const)] -pub struct InvalidAsmTemplateModifierConst { +pub(crate) struct InvalidAsmTemplateModifierConst { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -253,7 +253,7 @@ pub struct InvalidAsmTemplateModifierConst { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_sym)] -pub struct InvalidAsmTemplateModifierSym { +pub(crate) struct InvalidAsmTemplateModifierSym { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -263,7 +263,7 @@ pub struct InvalidAsmTemplateModifierSym { #[derive(Diagnostic)] #[diag(ast_lowering_invalid_asm_template_modifier_label)] -pub struct InvalidAsmTemplateModifierLabel { +pub(crate) struct InvalidAsmTemplateModifierLabel { #[primary_span] #[label(ast_lowering_template_modifier)] pub placeholder_span: Span, @@ -273,7 +273,7 @@ pub struct InvalidAsmTemplateModifierLabel { #[derive(Diagnostic)] #[diag(ast_lowering_register_class_only_clobber)] -pub struct RegisterClassOnlyClobber { +pub(crate) struct RegisterClassOnlyClobber { #[primary_span] pub op_span: Span, pub reg_class_name: Symbol, @@ -281,7 +281,7 @@ pub struct RegisterClassOnlyClobber { #[derive(Diagnostic)] #[diag(ast_lowering_register_conflict)] -pub struct RegisterConflict<'a> { +pub(crate) struct RegisterConflict<'a> { #[primary_span] #[label(ast_lowering_register1)] pub op_span1: Span, @@ -296,7 +296,7 @@ pub struct RegisterConflict<'a> { #[derive(Diagnostic)] #[help] #[diag(ast_lowering_sub_tuple_binding)] -pub struct SubTupleBinding<'a> { +pub(crate) struct SubTupleBinding<'a> { #[primary_span] #[label] #[suggestion( @@ -313,7 +313,7 @@ pub struct SubTupleBinding<'a> { #[derive(Diagnostic)] #[diag(ast_lowering_extra_double_dot)] -pub struct ExtraDoubleDot<'a> { +pub(crate) struct ExtraDoubleDot<'a> { #[primary_span] #[label] pub span: Span, @@ -325,21 +325,21 @@ pub struct ExtraDoubleDot<'a> { #[derive(Diagnostic)] #[note] #[diag(ast_lowering_misplaced_double_dot)] -pub struct MisplacedDoubleDot { +pub(crate) struct MisplacedDoubleDot { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_misplaced_relax_trait_bound)] -pub struct MisplacedRelaxTraitBound { +pub(crate) struct MisplacedRelaxTraitBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] -pub struct MatchArmWithNoBody { +pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] @@ -348,7 +348,7 @@ pub struct MatchArmWithNoBody { #[derive(Diagnostic)] #[diag(ast_lowering_never_pattern_with_body)] -pub struct NeverPatternWithBody { +pub(crate) struct NeverPatternWithBody { #[primary_span] #[label] #[suggestion(code = "", applicability = "maybe-incorrect")] @@ -357,7 +357,7 @@ pub struct NeverPatternWithBody { #[derive(Diagnostic)] #[diag(ast_lowering_never_pattern_with_guard)] -pub struct NeverPatternWithGuard { +pub(crate) struct NeverPatternWithGuard { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -365,7 +365,7 @@ pub struct NeverPatternWithGuard { #[derive(Diagnostic)] #[diag(ast_lowering_arbitrary_expression_in_pattern)] -pub struct ArbitraryExpressionInPattern { +pub(crate) struct ArbitraryExpressionInPattern { #[primary_span] pub span: Span, #[note(ast_lowering_pattern_from_macro_note)] @@ -374,13 +374,13 @@ pub struct ArbitraryExpressionInPattern { #[derive(Diagnostic)] #[diag(ast_lowering_inclusive_range_with_no_end)] -pub struct InclusiveRangeWithNoEnd { +pub(crate) struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -pub enum BadReturnTypeNotation { +pub(crate) enum BadReturnTypeNotation { #[diag(ast_lowering_bad_return_type_notation_inputs)] Inputs { #[primary_span] diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b5d8a547a8f..a6c7714a182 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -20,7 +20,7 @@ use super::errors::{ NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, }; use super::{ - ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs, ResolverAstLoweringExt, + GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; use crate::errors::YieldInClosure; use crate::{fluent_generated, FnDeclKind, ImplTraitPosition}; @@ -107,7 +107,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e.span, seg, ParamMode::Optional, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), // Method calls can't have bound modifiers None, @@ -387,7 +387,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !arg.is_potential_trivial_const_arg() { + if !self.tcx.features().const_arg_path || !arg.is_potential_trivial_const_arg() { // Add a definition for the in-band const def. self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index eef87879c24..c8ec8f308a8 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -764,18 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, (index, f): (usize, &FieldDef), ) -> hir::FieldDef<'hir> { - let ty = if let TyKind::Path(qself, path) = &f.ty.kind { - let t = self.lower_path_ty( - &f.ty, - qself, - path, - ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), - ); - self.arena.alloc(t) - } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) - }; + let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)); let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); hir::FieldDef { @@ -1188,7 +1177,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// into the body. This is to make sure that the future actually owns the /// arguments that are passed to the function, and to ensure things like /// drop order are stable. - pub fn lower_coroutine_body_with_moved_arguments( + pub(crate) fn lower_coroutine_body_with_moved_arguments( &mut self, decl: &FnDecl, lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 81d17a9dec2..bcc2c29a2ff 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -37,6 +37,7 @@ #![feature(box_patterns)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::collections::hash_map::Entry; @@ -481,13 +482,11 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { enum ParamMode { /// Any path in a type context. Explicit, - /// Path in a type definition, where the anonymous lifetime `'_` is not allowed. - ExplicitNamed, /// The `module::Type` in `module::Type::method` in an expression. Optional, } -enum ParenthesizedGenericArgs { +enum GenericArgsMode { ParenSugar, Err, } @@ -2358,7 +2357,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ) -> &'hir hir::ConstArg<'hir> { let ct_kind = match res { - Res::Def(DefKind::ConstParam, _) => { + Res::Def(DefKind::ConstParam, _) if self.tcx.features().const_arg_path => { let qpath = self.lower_qpath( ty_id, &None, @@ -2433,7 +2432,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); debug!("res={:?}", maybe_res); // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path - if let Some(res) = maybe_res + if self.tcx.features().const_arg_path + && let Some(res) = maybe_res && let Res::Def(DefKind::ConstParam, _) = res && let ExprKind::Path(qself, path) = &expr.kind { @@ -2464,7 +2464,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if c.value.is_potential_trivial_const_arg() { + if self.tcx.features().const_arg_path && c.value.is_potential_trivial_const_arg() { // HACK(min_generic_const_args): see DefCollector::visit_anon_const // Over there, we guess if this is a bare param and only create a def if // we think it's not. However we may can guess wrong (see there for example) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 077b06acd7c..2ab30eff6d8 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -15,8 +15,8 @@ use super::errors::{ GenericTypeWithParentheses, UseAngleBrackets, }; use super::{ - GenericArgsCtor, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, - ParenthesizedGenericArgs, ResolverAstLoweringExt, + GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, + ResolverAstLoweringExt, }; use crate::ImplTraitPosition; @@ -90,10 +90,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => param_mode, }; - let parenthesized_generic_args = match base_res { + let generic_args_mode = match base_res { // `a::b::Trait(Args)` Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { - ParenthesizedGenericArgs::ParenSugar + GenericArgsMode::ParenSugar } // `a::b::Trait(Args)::TraitItem` Res::Def(DefKind::AssocFn, _) @@ -101,19 +101,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => { - ParenthesizedGenericArgs::ParenSugar + GenericArgsMode::ParenSugar } // Avoid duplicated errors. - Res::Err => ParenthesizedGenericArgs::ParenSugar, + Res::Err => GenericArgsMode::ParenSugar, // An error - _ => ParenthesizedGenericArgs::Err, + _ => GenericArgsMode::Err, }; self.lower_path_segment( p.span, segment, param_mode, - parenthesized_generic_args, + generic_args_mode, itctx, bound_modifier_allowed_features.clone(), ) @@ -168,7 +168,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p.span, segment, param_mode, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, itctx, None, )); @@ -210,7 +210,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p.span, segment, param_mode, - ParenthesizedGenericArgs::Err, + GenericArgsMode::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ) @@ -224,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path_span: Span, segment: &PathSegment, param_mode: ParamMode, - parenthesized_generic_args: ParenthesizedGenericArgs, + generic_args_mode: GenericArgsMode, itctx: ImplTraitContext, // Additional features ungated with a bound modifier like `async`. // This is passed down to the implicit associated type binding in @@ -237,14 +237,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::AngleBracketed(data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } - GenericArgs::Parenthesized(data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::ParenSugar => self - .lower_parenthesized_parameter_data( - data, - itctx, - bound_modifier_allowed_features, - ), - ParenthesizedGenericArgs::Err => { + GenericArgs::Parenthesized(data) => match generic_args_mode { + GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data( + data, + itctx, + bound_modifier_allowed_features, + ), + GenericArgsMode::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` let sub = if !data.inputs.is_empty() { // Start of the span to the 1st character of 1st argument diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index de1b3f55e80..67c0396333c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -11,7 +11,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(ast_passes_visibility_not_permitted, code = E0449)] -pub struct VisibilityNotPermitted { +pub(crate) struct VisibilityNotPermitted { #[primary_span] pub span: Span, #[subdiagnostic] @@ -25,7 +25,7 @@ pub struct VisibilityNotPermitted { } #[derive(Subdiagnostic)] -pub enum VisibilityNotPermittedNote { +pub(crate) enum VisibilityNotPermittedNote { #[note(ast_passes_enum_variant)] EnumVariant, #[note(ast_passes_trait_impl)] @@ -38,7 +38,7 @@ pub enum VisibilityNotPermittedNote { #[derive(Diagnostic)] #[diag(ast_passes_trait_fn_const, code = E0379)] -pub struct TraitFnConst { +pub(crate) struct TraitFnConst { #[primary_span] #[label] pub span: Span, @@ -64,21 +64,21 @@ pub struct TraitFnConst { #[derive(Diagnostic)] #[diag(ast_passes_forbidden_bound)] -pub struct ForbiddenBound { +pub(crate) struct ForbiddenBound { #[primary_span] pub spans: Vec<Span>, } #[derive(Diagnostic)] #[diag(ast_passes_forbidden_const_param)] -pub struct ForbiddenConstParam { +pub(crate) struct ForbiddenConstParam { #[primary_span] pub const_param_spans: Vec<Span>, } #[derive(Diagnostic)] #[diag(ast_passes_fn_param_too_many)] -pub struct FnParamTooMany { +pub(crate) struct FnParamTooMany { #[primary_span] pub span: Span, pub max_num_args: usize, @@ -86,14 +86,14 @@ pub struct FnParamTooMany { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_c_var_args_not_last)] -pub struct FnParamCVarArgsNotLast { +pub(crate) struct FnParamCVarArgsNotLast { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_fn_param_doc_comment)] -pub struct FnParamDocComment { +pub(crate) struct FnParamDocComment { #[primary_span] #[label] pub span: Span, @@ -101,7 +101,7 @@ pub struct FnParamDocComment { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_forbidden_attr)] -pub struct FnParamForbiddenAttr { +pub(crate) struct FnParamForbiddenAttr { #[primary_span] pub span: Span, } @@ -109,7 +109,7 @@ pub struct FnParamForbiddenAttr { #[derive(Diagnostic)] #[diag(ast_passes_fn_param_forbidden_self)] #[note] -pub struct FnParamForbiddenSelf { +pub(crate) struct FnParamForbiddenSelf { #[primary_span] #[label] pub span: Span, @@ -117,7 +117,7 @@ pub struct FnParamForbiddenSelf { #[derive(Diagnostic)] #[diag(ast_passes_forbidden_default)] -pub struct ForbiddenDefault { +pub(crate) struct ForbiddenDefault { #[primary_span] pub span: Span, #[label] @@ -126,7 +126,7 @@ pub struct ForbiddenDefault { #[derive(Diagnostic)] #[diag(ast_passes_assoc_const_without_body)] -pub struct AssocConstWithoutBody { +pub(crate) struct AssocConstWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] @@ -135,7 +135,7 @@ pub struct AssocConstWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_assoc_fn_without_body)] -pub struct AssocFnWithoutBody { +pub(crate) struct AssocFnWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")] @@ -144,7 +144,7 @@ pub struct AssocFnWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_assoc_type_without_body)] -pub struct AssocTypeWithoutBody { +pub(crate) struct AssocTypeWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = <type>;", applicability = "has-placeholders")] @@ -153,7 +153,7 @@ pub struct AssocTypeWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_const_without_body)] -pub struct ConstWithoutBody { +pub(crate) struct ConstWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] @@ -162,7 +162,7 @@ pub struct ConstWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_static_without_body)] -pub struct StaticWithoutBody { +pub(crate) struct StaticWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] @@ -171,7 +171,7 @@ pub struct StaticWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_ty_alias_without_body)] -pub struct TyAliasWithoutBody { +pub(crate) struct TyAliasWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " = <type>;", applicability = "has-placeholders")] @@ -180,7 +180,7 @@ pub struct TyAliasWithoutBody { #[derive(Diagnostic)] #[diag(ast_passes_fn_without_body)] -pub struct FnWithoutBody { +pub(crate) struct FnWithoutBody { #[primary_span] pub span: Span, #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")] @@ -190,7 +190,7 @@ pub struct FnWithoutBody { } #[derive(Subdiagnostic)] -pub enum ExternBlockSuggestion { +pub(crate) enum ExternBlockSuggestion { #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] Implicit { #[suggestion_part(code = "extern {{")] @@ -210,7 +210,7 @@ pub enum ExternBlockSuggestion { #[derive(Diagnostic)] #[diag(ast_passes_extern_invalid_safety)] -pub struct InvalidSafetyOnExtern { +pub(crate) struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] @@ -219,28 +219,28 @@ pub struct InvalidSafetyOnExtern { #[derive(Diagnostic)] #[diag(ast_passes_item_invalid_safety)] -pub struct InvalidSafetyOnItem { +pub(crate) struct InvalidSafetyOnItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_bare_fn_invalid_safety)] -pub struct InvalidSafetyOnBareFn { +pub(crate) struct InvalidSafetyOnBareFn { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_unsafe_static)] -pub struct UnsafeStatic { +pub(crate) struct UnsafeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_bound_in_context)] -pub struct BoundInContext<'a> { +pub(crate) struct BoundInContext<'a> { #[primary_span] pub span: Span, pub ctx: &'a str, @@ -249,7 +249,7 @@ pub struct BoundInContext<'a> { #[derive(Diagnostic)] #[diag(ast_passes_extern_types_cannot)] #[note(ast_passes_extern_keyword_link)] -pub struct ExternTypesCannotHave<'a> { +pub(crate) struct ExternTypesCannotHave<'a> { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -262,7 +262,7 @@ pub struct ExternTypesCannotHave<'a> { #[derive(Diagnostic)] #[diag(ast_passes_body_in_extern)] #[note(ast_passes_extern_keyword_link)] -pub struct BodyInExtern<'a> { +pub(crate) struct BodyInExtern<'a> { #[primary_span] #[label(ast_passes_cannot_have)] pub span: Span, @@ -277,7 +277,7 @@ pub struct BodyInExtern<'a> { #[diag(ast_passes_fn_body_extern)] #[help] #[note(ast_passes_extern_keyword_link)] -pub struct FnBodyInExtern { +pub(crate) struct FnBodyInExtern { #[primary_span] #[label(ast_passes_cannot_have)] pub span: Span, @@ -289,7 +289,7 @@ pub struct FnBodyInExtern { #[derive(Diagnostic)] #[diag(ast_passes_extern_fn_qualifiers)] -pub struct FnQualifierInExtern { +pub(crate) struct FnQualifierInExtern { #[primary_span] #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, @@ -300,7 +300,7 @@ pub struct FnQualifierInExtern { #[derive(Diagnostic)] #[diag(ast_passes_extern_item_ascii)] #[note] -pub struct ExternItemAscii { +pub(crate) struct ExternItemAscii { #[primary_span] pub span: Span, #[label] @@ -309,14 +309,14 @@ pub struct ExternItemAscii { #[derive(Diagnostic)] #[diag(ast_passes_bad_c_variadic)] -pub struct BadCVariadic { +pub(crate) struct BadCVariadic { #[primary_span] pub span: Vec<Span>, } #[derive(Diagnostic)] #[diag(ast_passes_item_underscore)] -pub struct ItemUnderscore<'a> { +pub(crate) struct ItemUnderscore<'a> { #[primary_span] #[label] pub span: Span, @@ -325,7 +325,7 @@ pub struct ItemUnderscore<'a> { #[derive(Diagnostic)] #[diag(ast_passes_nomangle_ascii, code = E0754)] -pub struct NoMangleAscii { +pub(crate) struct NoMangleAscii { #[primary_span] pub span: Span, } @@ -333,7 +333,7 @@ pub struct NoMangleAscii { #[derive(Diagnostic)] #[diag(ast_passes_module_nonascii, code = E0754)] #[help] -pub struct ModuleNonAscii { +pub(crate) struct ModuleNonAscii { #[primary_span] pub span: Span, pub name: Symbol, @@ -341,7 +341,7 @@ pub struct ModuleNonAscii { #[derive(Diagnostic)] #[diag(ast_passes_auto_generic, code = E0567)] -pub struct AutoTraitGeneric { +pub(crate) struct AutoTraitGeneric { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -351,7 +351,7 @@ pub struct AutoTraitGeneric { #[derive(Diagnostic)] #[diag(ast_passes_auto_super_lifetime, code = E0568)] -pub struct AutoTraitBounds { +pub(crate) struct AutoTraitBounds { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub span: Span, @@ -361,7 +361,7 @@ pub struct AutoTraitBounds { #[derive(Diagnostic)] #[diag(ast_passes_auto_items, code = E0380)] -pub struct AutoTraitItems { +pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec<Span>, #[suggestion(code = "", applicability = "machine-applicable")] @@ -372,7 +372,7 @@ pub struct AutoTraitItems { #[derive(Diagnostic)] #[diag(ast_passes_generic_before_constraints)] -pub struct ArgsBeforeConstraint { +pub(crate) struct ArgsBeforeConstraint { #[primary_span] pub arg_spans: Vec<Span>, #[label(ast_passes_constraints)] @@ -390,7 +390,7 @@ pub struct ArgsBeforeConstraint { pub arg_spans2: EmptyLabelManySpans, } -pub struct EmptyLabelManySpans(pub Vec<Span>); +pub(crate) struct EmptyLabelManySpans(pub Vec<Span>); // The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each impl Subdiagnostic for EmptyLabelManySpans { @@ -405,28 +405,28 @@ impl Subdiagnostic for EmptyLabelManySpans { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_fn_pointer, code = E0561)] -pub struct PatternFnPointer { +pub(crate) struct PatternFnPointer { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_trait_object_single_bound, code = E0226)] -pub struct TraitObjectBound { +pub(crate) struct TraitObjectBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_impl_trait_path, code = E0667)] -pub struct ImplTraitPath { +pub(crate) struct ImplTraitPath { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_nested_impl_trait, code = E0666)] -pub struct NestedImplTrait { +pub(crate) struct NestedImplTrait { #[primary_span] pub span: Span, #[label(ast_passes_outer)] @@ -437,14 +437,14 @@ pub struct NestedImplTrait { #[derive(Diagnostic)] #[diag(ast_passes_at_least_one_trait)] -pub struct AtLeastOneTrait { +pub(crate) struct AtLeastOneTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_out_of_order_params)] -pub struct OutOfOrderParams<'a> { +pub(crate) struct OutOfOrderParams<'a> { #[primary_span] pub spans: Vec<Span>, #[suggestion(code = "{ordered_params}", applicability = "machine-applicable")] @@ -457,14 +457,14 @@ pub struct OutOfOrderParams<'a> { #[derive(Diagnostic)] #[diag(ast_passes_obsolete_auto)] #[help] -pub struct ObsoleteAuto { +pub(crate) struct ObsoleteAuto { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_unsafe_negative_impl, code = E0198)] -pub struct UnsafeNegativeImpl { +pub(crate) struct UnsafeNegativeImpl { #[primary_span] pub span: Span, #[label(ast_passes_negative)] @@ -475,7 +475,7 @@ pub struct UnsafeNegativeImpl { #[derive(Diagnostic)] #[diag(ast_passes_inherent_cannot_be)] -pub struct InherentImplCannot<'a> { +pub(crate) struct InherentImplCannot<'a> { #[primary_span] pub span: Span, #[label(ast_passes_because)] @@ -489,7 +489,7 @@ pub struct InherentImplCannot<'a> { #[derive(Diagnostic)] #[diag(ast_passes_inherent_cannot_be, code = E0197)] -pub struct InherentImplCannotUnsafe<'a> { +pub(crate) struct InherentImplCannotUnsafe<'a> { #[primary_span] pub span: Span, #[label(ast_passes_because)] @@ -501,7 +501,7 @@ pub struct InherentImplCannotUnsafe<'a> { #[derive(Diagnostic)] #[diag(ast_passes_unsafe_item)] -pub struct UnsafeItem { +pub(crate) struct UnsafeItem { #[primary_span] pub span: Span, pub kind: &'static str, @@ -509,14 +509,14 @@ pub struct UnsafeItem { #[derive(Diagnostic)] #[diag(ast_passes_missing_unsafe_on_extern)] -pub struct MissingUnsafeOnExtern { +pub(crate) struct MissingUnsafeOnExtern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_fieldless_union)] -pub struct FieldlessUnion { +pub(crate) struct FieldlessUnion { #[primary_span] pub span: Span, } @@ -524,7 +524,7 @@ pub struct FieldlessUnion { #[derive(Diagnostic)] #[diag(ast_passes_where_clause_after_type_alias)] #[note] -pub struct WhereClauseAfterTypeAlias { +pub(crate) struct WhereClauseAfterTypeAlias { #[primary_span] pub span: Span, #[help] @@ -534,7 +534,7 @@ pub struct WhereClauseAfterTypeAlias { #[derive(Diagnostic)] #[diag(ast_passes_where_clause_before_type_alias)] #[note] -pub struct WhereClauseBeforeTypeAlias { +pub(crate) struct WhereClauseBeforeTypeAlias { #[primary_span] pub span: Span, #[subdiagnostic] @@ -543,7 +543,7 @@ pub struct WhereClauseBeforeTypeAlias { #[derive(Subdiagnostic)] -pub enum WhereClauseBeforeTypeAliasSugg { +pub(crate) enum WhereClauseBeforeTypeAliasSugg { #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] Remove { #[primary_span] @@ -565,14 +565,14 @@ pub enum WhereClauseBeforeTypeAliasSugg { #[derive(Diagnostic)] #[diag(ast_passes_generic_default_trailing)] -pub struct GenericDefaultTrailing { +pub(crate) struct GenericDefaultTrailing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_nested_lifetimes, code = E0316)] -pub struct NestedLifetimes { +pub(crate) struct NestedLifetimes { #[primary_span] pub span: Span, } @@ -580,7 +580,7 @@ pub struct NestedLifetimes { #[derive(Diagnostic)] #[diag(ast_passes_optional_trait_supertrait)] #[note] -pub struct OptionalTraitSupertrait { +pub(crate) struct OptionalTraitSupertrait { #[primary_span] pub span: Span, pub path_str: String, @@ -588,14 +588,14 @@ pub struct OptionalTraitSupertrait { #[derive(Diagnostic)] #[diag(ast_passes_optional_trait_object)] -pub struct OptionalTraitObject { +pub(crate) struct OptionalTraitObject { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_const_bound_trait_object)] -pub struct ConstBoundTraitObject { +pub(crate) struct ConstBoundTraitObject { #[primary_span] pub span: Span, } @@ -604,7 +604,7 @@ pub struct ConstBoundTraitObject { // FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] -pub struct TildeConstDisallowed { +pub(crate) struct TildeConstDisallowed { #[primary_span] pub span: Span, #[subdiagnostic] @@ -612,7 +612,7 @@ pub struct TildeConstDisallowed { } #[derive(Subdiagnostic, Copy, Clone)] -pub enum TildeConstReason { +pub(crate) enum TildeConstReason { #[note(ast_passes_closure)] Closure, #[note(ast_passes_function)] @@ -658,7 +658,7 @@ pub enum TildeConstReason { #[derive(Diagnostic)] #[diag(ast_passes_const_and_async)] -pub struct ConstAndAsync { +pub(crate) struct ConstAndAsync { #[primary_span] pub spans: Vec<Span>, #[label(ast_passes_const)] @@ -671,7 +671,7 @@ pub struct ConstAndAsync { #[derive(Diagnostic)] #[diag(ast_passes_const_and_c_variadic)] -pub struct ConstAndCVariadic { +pub(crate) struct ConstAndCVariadic { #[primary_span] pub spans: Vec<Span>, #[label(ast_passes_const)] @@ -683,7 +683,7 @@ pub struct ConstAndCVariadic { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_foreign, code = E0130)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) -pub struct PatternInForeign { +pub(crate) struct PatternInForeign { #[primary_span] #[label] pub span: Span, @@ -692,7 +692,7 @@ pub struct PatternInForeign { #[derive(Diagnostic)] #[diag(ast_passes_pattern_in_bodiless, code = E0642)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) -pub struct PatternInBodiless { +pub(crate) struct PatternInBodiless { #[primary_span] #[label] pub span: Span, @@ -701,7 +701,7 @@ pub struct PatternInBodiless { #[derive(Diagnostic)] #[diag(ast_passes_equality_in_where)] #[note] -pub struct EqualityInWhere { +pub(crate) struct EqualityInWhere { #[primary_span] #[label] pub span: Span, @@ -718,7 +718,7 @@ pub struct EqualityInWhere { style = "verbose", applicability = "maybe-incorrect" )] -pub struct AssociatedSuggestion { +pub(crate) struct AssociatedSuggestion { #[primary_span] pub span: Span, pub ident: Ident, @@ -728,7 +728,7 @@ pub struct AssociatedSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion(ast_passes_suggestion_path, applicability = "maybe-incorrect")] -pub struct AssociatedSuggestion2 { +pub(crate) struct AssociatedSuggestion2 { #[suggestion_part(code = "{args}")] pub span: Span, pub args: String, @@ -740,14 +740,14 @@ pub struct AssociatedSuggestion2 { #[derive(Diagnostic)] #[diag(ast_passes_stability_outside_std, code = E0734)] -pub struct StabilityOutsideStd { +pub(crate) struct StabilityOutsideStd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_feature_on_non_nightly, code = E0554)] -pub struct FeatureOnNonNightly { +pub(crate) struct FeatureOnNonNightly { #[primary_span] pub span: Span, pub channel: &'static str, @@ -757,7 +757,7 @@ pub struct FeatureOnNonNightly { pub sugg: Option<Span>, } -pub struct StableFeature { +pub(crate) struct StableFeature { pub name: Symbol, pub since: Symbol, } @@ -777,7 +777,7 @@ impl Subdiagnostic for StableFeature { #[derive(Diagnostic)] #[diag(ast_passes_incompatible_features)] #[help] -pub struct IncompatibleFeatures { +pub(crate) struct IncompatibleFeatures { #[primary_span] pub spans: Vec<Span>, pub f1: Symbol, @@ -786,7 +786,7 @@ pub struct IncompatibleFeatures { #[derive(Diagnostic)] #[diag(ast_passes_show_span)] -pub struct ShowSpan { +pub(crate) struct ShowSpan { #[primary_span] pub span: Span, pub msg: &'static str, @@ -794,28 +794,28 @@ pub struct ShowSpan { #[derive(Diagnostic)] #[diag(ast_passes_negative_bound_not_supported)] -pub struct NegativeBoundUnsupported { +pub(crate) struct NegativeBoundUnsupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_constraint_on_negative_bound)] -pub struct ConstraintOnNegativeBound { +pub(crate) struct ConstraintOnNegativeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_negative_bound_with_parenthetical_notation)] -pub struct NegativeBoundWithParentheticalNotation { +pub(crate) struct NegativeBoundWithParentheticalNotation { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ast_passes_invalid_unnamed_field_ty)] -pub struct InvalidUnnamedFieldTy { +pub(crate) struct InvalidUnnamedFieldTy { #[primary_span] pub span: Span, #[label] @@ -824,7 +824,7 @@ pub struct InvalidUnnamedFieldTy { #[derive(Diagnostic)] #[diag(ast_passes_invalid_unnamed_field)] -pub struct InvalidUnnamedField { +pub(crate) struct InvalidUnnamedField { #[primary_span] pub span: Span, #[label] @@ -833,7 +833,7 @@ pub struct InvalidUnnamedField { #[derive(Diagnostic)] #[diag(ast_passes_anon_struct_or_union_not_allowed)] -pub struct AnonStructOrUnionNotAllowed { +pub(crate) struct AnonStructOrUnionNotAllowed { #[primary_span] #[label] pub span: Span, @@ -842,7 +842,7 @@ pub struct AnonStructOrUnionNotAllowed { #[derive(Diagnostic)] #[diag(ast_passes_match_arm_with_no_body)] -pub struct MatchArmWithNoBody { +pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] @@ -851,7 +851,7 @@ pub struct MatchArmWithNoBody { #[derive(Diagnostic)] #[diag(ast_passes_precise_capturing_not_allowed_here)] -pub struct PreciseCapturingNotAllowedHere { +pub(crate) struct PreciseCapturingNotAllowedHere { #[primary_span] pub span: Span, pub loc: &'static str, @@ -859,7 +859,7 @@ pub struct PreciseCapturingNotAllowedHere { #[derive(Diagnostic)] #[diag(ast_passes_precise_capturing_duplicated)] -pub struct DuplicatePreciseCapturing { +pub(crate) struct DuplicatePreciseCapturing { #[primary_span] pub bound1: Span, #[label] diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 1f4bcd59afa..88c6bde3106 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -12,6 +12,7 @@ #![feature(iter_is_partitioned)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod ast_validation; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 84d9ce278a2..602ab69ee5b 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -3,6 +3,7 @@ #![doc(rust_logo)] #![feature(box_patterns)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 6d46c26311b..7559b181f7d 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -89,7 +89,7 @@ impl Printer { } impl Token { - pub fn is_hardbreak_tok(&self) -> bool { + pub(crate) fn is_hardbreak_tok(&self) -> bool { *self == Printer::hardbreak_tok_offset(0) } } diff --git a/compiler/rustc_ast_pretty/src/pp/ring.rs b/compiler/rustc_ast_pretty/src/pp/ring.rs index 8187394fe30..003c0a999b5 100644 --- a/compiler/rustc_ast_pretty/src/pp/ring.rs +++ b/compiler/rustc_ast_pretty/src/pp/ring.rs @@ -11,54 +11,54 @@ use std::ops::{Index, IndexMut}; /// Holding a RingBuffer whose view is elements left..right gives the ability to /// use Index and IndexMut to access elements i in the infinitely long queue for /// which left <= i < right. -pub struct RingBuffer<T> { +pub(super) struct RingBuffer<T> { data: VecDeque<T>, // Abstract index of data[0] in the infinitely sized queue. offset: usize, } impl<T> RingBuffer<T> { - pub fn new() -> Self { + pub(super) fn new() -> Self { RingBuffer { data: VecDeque::new(), offset: 0 } } - pub fn is_empty(&self) -> bool { + pub(super) fn is_empty(&self) -> bool { self.data.is_empty() } - pub fn push(&mut self, value: T) -> usize { + pub(super) fn push(&mut self, value: T) -> usize { let index = self.offset + self.data.len(); self.data.push_back(value); index } - pub fn clear(&mut self) { + pub(super) fn clear(&mut self) { self.data.clear(); } - pub fn index_of_first(&self) -> usize { + pub(super) fn index_of_first(&self) -> usize { self.offset } - pub fn first(&self) -> Option<&T> { + pub(super) fn first(&self) -> Option<&T> { self.data.front() } - pub fn first_mut(&mut self) -> Option<&mut T> { + pub(super) fn first_mut(&mut self) -> Option<&mut T> { self.data.front_mut() } - pub fn pop_first(&mut self) -> Option<T> { + pub(super) fn pop_first(&mut self) -> Option<T> { let first = self.data.pop_front()?; self.offset += 1; Some(first) } - pub fn last(&self) -> Option<&T> { + pub(super) fn last(&self) -> Option<&T> { self.data.back() } - pub fn last_mut(&mut self) -> Option<&mut T> { + pub(super) fn last_mut(&mut self) -> Option<&mut T> { self.data.back_mut() } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs index 86d4796e9ce..c9baca72485 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/fixup.rs @@ -110,13 +110,13 @@ impl Default for FixupContext { impl FixupContext { /// Create the initial fixup for printing an expression in statement /// position. - pub fn new_stmt() -> Self { + pub(crate) fn new_stmt() -> Self { FixupContext { stmt: true, ..FixupContext::default() } } /// Create the initial fixup for printing an expression as the right-hand /// side of a match arm. - pub fn new_match_arm() -> Self { + pub(crate) fn new_match_arm() -> Self { FixupContext { match_arm: true, ..FixupContext::default() } } @@ -124,7 +124,7 @@ impl FixupContext { /// of an `if` or `while`. There are a few other positions which are /// grammatically equivalent and also use this, such as the iterator /// expression in `for` and the scrutinee in `match`. - pub fn new_cond() -> Self { + pub(crate) fn new_cond() -> Self { FixupContext { parenthesize_exterior_struct_lit: true, ..FixupContext::default() } } @@ -139,7 +139,7 @@ impl FixupContext { /// /// Not every expression has a leftmost subexpression. For example neither /// `-$a` nor `[$a]` have one. - pub fn leftmost_subexpression(self) -> Self { + pub(crate) fn leftmost_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt, @@ -158,7 +158,7 @@ impl FixupContext { /// current expression, and is not surrounded by a paren/bracket/brace. For /// example the `$b` in `$a + $b` and `-$b`, but not the one in `[$b]` or /// `$a.f($b)`. - pub fn subsequent_subexpression(self) -> Self { + pub(crate) fn subsequent_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, @@ -173,7 +173,7 @@ impl FixupContext { /// /// The documentation on `FixupContext::leftmost_subexpression_in_stmt` has /// examples. - pub fn would_cause_statement_boundary(self, expr: &Expr) -> bool { + pub(crate) fn would_cause_statement_boundary(self, expr: &Expr) -> bool { (self.leftmost_subexpression_in_stmt && !classify::expr_requires_semi_to_be_stmt(expr)) || (self.leftmost_subexpression_in_match_arm && classify::expr_is_complete(expr)) } @@ -189,7 +189,7 @@ impl FixupContext { /// /// - `true && false`, because otherwise this would be misinterpreted as a /// "let chain". - pub fn needs_par_as_let_scrutinee(self, expr: &Expr) -> bool { + pub(crate) fn needs_par_as_let_scrutinee(self, expr: &Expr) -> bool { self.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr) || parser::needs_par_as_let_scrutinee(expr.precedence().order()) } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 1ecfc42ec1d..0dad6372389 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -9,6 +9,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod builtin; diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 9b69325a053..234a0ef28a2 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -127,7 +127,7 @@ pub(crate) enum InvalidIssueStringCause { } impl InvalidIssueStringCause { - pub fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option<Self> { + pub(crate) fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option<Self> { match kind { IntErrorKind::Empty => Some(Self::Empty { span }), IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }), @@ -303,7 +303,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> { } impl<'a> IncorrectReprFormatGenericCause<'a> { - pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> { + pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> { match kind { ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { Some(Self::Int { span, name, int: int.get() }) diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs index e964a709757..f86a9db61c6 100644 --- a/compiler/rustc_baked_icu_data/src/lib.rs +++ b/compiler/rustc_baked_icu_data/src/lib.rs @@ -25,6 +25,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code // tidy-alphabetical-end mod data { diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 76e39fe94af..2c672dbf8c4 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { - pub fn dcx(&self) -> DiagCtxtHandle<'infcx> { + pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> { self.infcx.dcx() } @@ -290,7 +290,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { ty: Ty<'_>, is_index: Option<bool>, ) -> Diag<'infcx> { - let type_name = match (&ty.kind(), is_index) { + let type_name = match (ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 77794a8525f..2795bc7162f 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -14,7 +14,7 @@ use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, Results, ResultsVisi use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// The results of the dataflow analyses used by the borrow checker. -pub struct BorrowckResults<'a, 'mir, 'tcx> { +pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> { pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>, pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>, @@ -22,7 +22,7 @@ pub struct BorrowckResults<'a, 'mir, 'tcx> { /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] -pub struct BorrowckFlowState<'a, 'mir, 'tcx> { +pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> { pub(crate) borrows: <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain, pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain, pub(crate) ever_inits: <EverInitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain, diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index e07d7dd309a..263f68d6a3d 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -4,13 +4,13 @@ use rustc_middle::mir::visit::{ }; #[derive(Eq, PartialEq, Clone)] -pub enum DefUse { +pub(crate) enum DefUse { Def, Use, Drop, } -pub fn categorize(context: PlaceContext) -> Option<DefUse> { +pub(crate) fn categorize(context: PlaceContext) -> Option<DefUse> { match context { /////////////////////////////////////////////////////////////////////////// // DEFS diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2b46e5597f7..aaeedde2bed 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -645,7 +645,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } } - pub fn suggest_reborrow( + pub(crate) fn suggest_reborrow( &self, err: &mut Diag<'infcx>, span: Span, @@ -678,14 +678,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { let inits = &self.move_data.init_path_map[mpi]; let move_path = &self.move_data.move_paths[mpi]; let decl_span = self.body.local_decls[move_path.place.local].source_info.span; - let mut spans = vec![]; + let mut spans_set = FxIndexSet::default(); for init_idx in inits { let init = &self.move_data.inits[*init_idx]; let span = init.span(self.body); if !span.is_dummy() { - spans.push(span); + spans_set.insert(span); } } + let spans: Vec<_> = spans_set.into_iter().collect(); let (name, desc) = match self.describe_place_with_options( moved_place, @@ -1891,10 +1892,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { struct FindUselessClone<'tcx> { tcx: TyCtxt<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, - pub clones: Vec<&'tcx hir::Expr<'tcx>>, + clones: Vec<&'tcx hir::Expr<'tcx>>, } impl<'tcx> FindUselessClone<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { Self { tcx, typeck_results: tcx.typeck(def_id), clones: vec![] } } } @@ -1916,7 +1917,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { let body = hir.body(body_id).value; expr_finder.visit_expr(body); - pub struct Holds<'tcx> { + struct Holds<'tcx> { ty: Ty<'tcx>, } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index a2e5c7b8514..33f91d7ad30 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -58,11 +58,11 @@ pub(crate) use region_name::{RegionName, RegionNameSource}; pub(crate) use rustc_middle::util::CallKind; pub(super) struct DescribePlaceOpt { - pub including_downcast: bool, + including_downcast: bool, /// Enable/Disable tuple fields. /// For example `x` tuple. if it's `true` `x.0`. Otherwise `x` - pub including_tuple_field: bool, + including_tuple_field: bool, } pub(super) struct IncludingTupleField(pub(super) bool); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 792f1548e08..42b1ffd58ad 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -16,7 +16,7 @@ use crate::prefixes::PrefixSet; use crate::MirBorrowckCtxt; #[derive(Debug)] -pub enum IllegalMoveOriginKind<'tcx> { +pub(crate) enum IllegalMoveOriginKind<'tcx> { /// Illegal move due to attempt to move from behind a reference. BorrowedContent { /// The place the reference refers to: if erroneous code was trying to diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0303b80cace..7b791928689 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1374,7 +1374,7 @@ impl<'tcx> Visitor<'tcx> for BindingFinder { } } -pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool { +fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool { debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind()); match *local_decl.local_info() { diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index de0df347429..a59b7b3cde9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -31,7 +31,7 @@ enum SuggestedConstraint { /// /// Adds a help note suggesting adding a where clause with the needed constraints. #[derive(Default)] -pub struct OutlivesSuggestionBuilder { +pub(crate) struct OutlivesSuggestionBuilder { /// The list of outlives constraints that need to be added. Specifically, we map each free /// region to all other regions that it must outlive. I will use the shorthand `fr: /// outlived_frs`. Not all of these regions will already have names necessarily. Some could be diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 451e8bcb16d..ab48a09cfa4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -72,22 +72,24 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { pub(crate) struct RegionErrors<'tcx>(Vec<(RegionErrorKind<'tcx>, ErrorGuaranteed)>, TyCtxt<'tcx>); impl<'tcx> RegionErrors<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self { Self(vec![], tcx) } #[track_caller] - pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) { + pub(crate) fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) { let val = val.into(); let guar = self.1.sess.dcx().delayed_bug(format!("{val:?}")); self.0.push((val, guar)); } - pub fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.0.is_empty() } - pub fn into_iter(self) -> impl Iterator<Item = (RegionErrorKind<'tcx>, ErrorGuaranteed)> { + pub(crate) fn into_iter( + self, + ) -> impl Iterator<Item = (RegionErrorKind<'tcx>, ErrorGuaranteed)> { self.0.into_iter() } - pub fn has_errors(&self) -> Option<ErrorGuaranteed> { + pub(crate) fn has_errors(&self) -> Option<ErrorGuaranteed> { self.0.get(0).map(|x| x.1) } } @@ -141,7 +143,7 @@ pub(crate) enum RegionErrorKind<'tcx> { /// Information about the various region constraints involved in a borrow checker error. #[derive(Clone, Debug)] -pub struct ErrorConstraintInfo<'tcx> { +pub(crate) struct ErrorConstraintInfo<'tcx> { // fr: outlived_fr pub(super) fr: RegionVid, pub(super) fr_is_local: bool, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a529df76bcb..bb1aea14693 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -12,6 +12,7 @@ #![feature(rustdoc_internals)] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -2444,7 +2445,7 @@ mod diags { } } - pub struct BorrowckDiags<'infcx, 'tcx> { + pub(crate) struct BorrowckDiags<'infcx, 'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. /// /// There are situations where many errors can be reported for a single move out (see @@ -2468,7 +2469,7 @@ mod diags { } impl<'infcx, 'tcx> BorrowckDiags<'infcx, 'tcx> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { BorrowckDiags { buffered_move_errors: BTreeMap::new(), buffered_mut_errors: Default::default(), @@ -2476,25 +2477,25 @@ mod diags { } } - pub fn buffer_error(&mut self, diag: Diag<'infcx>) { + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.buffered_diags.push(BufferedDiag::Error(diag)); } - pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.buffered_diags.push(BufferedDiag::NonError(diag)); } } impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { - pub fn buffer_error(&mut self, diag: Diag<'infcx>) { + pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.diags.buffer_error(diag); } - pub fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { + pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) { self.diags.buffer_non_error(diag); } - pub fn buffer_move_error( + pub(crate) fn buffer_move_error( &mut self, move_out_indices: Vec<MoveOutIndex>, place_and_err: (PlaceRef<'tcx>, Diag<'infcx>), @@ -2510,16 +2511,19 @@ mod diags { } } - pub fn get_buffered_mut_error(&mut self, span: Span) -> Option<(Diag<'infcx>, usize)> { + pub(crate) fn get_buffered_mut_error( + &mut self, + span: Span, + ) -> Option<(Diag<'infcx>, usize)> { // FIXME(#120456) - is `swap_remove` correct? self.diags.buffered_mut_errors.swap_remove(&span) } - pub fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { + pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count: usize) { self.diags.buffered_mut_errors.insert(span, (diag, count)); } - pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { + pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { let mut res = None; // Buffer any move errors that we collected and de-duplicated. @@ -2553,7 +2557,7 @@ mod diags { self.diags.buffered_diags.is_empty() } - pub fn has_move_error( + pub(crate) fn has_move_error( &self, move_out_indices: &[MoveOutIndex], ) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> { diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 42d0c2038f8..311f17f15b9 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -201,7 +201,7 @@ fn place_components_conflict<'tcx>( let base_ty = base.ty(body, tcx).ty; - match (elem, &base_ty.kind(), access) { + match (elem, base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::FakeBorrow))) => { // The array length is like additional fields on the diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index d3bfd1c418f..39d831378cd 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{PlaceRef, ProjectionElem}; use super::MirBorrowckCtxt; -pub trait IsPrefixOf<'tcx> { +pub(crate) trait IsPrefixOf<'tcx> { fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index c8dc012de4a..6cbdd890b5e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -42,9 +42,9 @@ mod graphviz; mod opaque_types; mod reverse_sccs; -pub mod values; +pub(crate) mod values; -pub type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>; +pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>; /// An annotation for region graph SCCs that tracks /// the values of its elements. @@ -226,7 +226,7 @@ pub(crate) struct AppliedMemberConstraint { } #[derive(Debug)] -pub struct RegionDefinition<'tcx> { +pub(crate) struct RegionDefinition<'tcx> { /// What kind of variable is this -- a free region? existential /// variable? etc. (See the `NllRegionVariableOrigin` for more /// info.) @@ -288,7 +288,7 @@ pub(crate) enum Cause { /// `InferCtxt::process_registered_region_obligations` and /// `InferCtxt::type_must_outlive` in `rustc_infer::infer::InferCtxt`. #[derive(Clone, Debug)] -pub struct TypeTest<'tcx> { +pub(crate) struct TypeTest<'tcx> { /// The type `T` that must outlive the region. pub generic_kind: GenericKind<'tcx>, @@ -320,7 +320,7 @@ enum Trace<'tcx> { } #[derive(Clone, PartialEq, Eq, Debug)] -pub enum ExtraConstraintInfo { +pub(crate) enum ExtraConstraintInfo { PlaceholderFromPredicate(Span), } @@ -2259,7 +2259,7 @@ impl<'tcx> RegionDefinition<'tcx> { } #[derive(Clone, Debug)] -pub struct BlameConstraint<'tcx> { +pub(crate) struct BlameConstraint<'tcx> { pub category: ConstraintCategory<'tcx>, pub from_closure: bool, pub cause: ObligationCause<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 1073ea40694..cd66acd0a8f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -473,20 +473,20 @@ struct LazyOpaqueTyEnv<'tcx> { } impl<'tcx> LazyOpaqueTyEnv<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() } } - pub fn param_equal_static(&self, param_index: usize) -> bool { + fn param_equal_static(&self, param_index: usize) -> bool { self.get_canonical_args()[param_index].expect_region().is_static() } - pub fn params_equal(&self, param1: usize, param2: usize) -> bool { + fn params_equal(&self, param1: usize, param2: usize) -> bool { let canonical_args = self.get_canonical_args(); canonical_args[param1] == canonical_args[param2] } - pub fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { + fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { self.get_canonical_args()[param_index].error_reported() } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6983cda6ddf..d8f74840eb5 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -86,7 +86,7 @@ macro_rules! span_mirbug_and_err { mod canonical; mod constraint_conversion; -pub mod free_region_relations; +pub(crate) mod free_region_relations; mod input_output; pub(crate) mod liveness; mod relate_tys; @@ -2043,9 +2043,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); - if let Err(terr) = self.eq_types( - *ty, + if let Err(terr) = self.sub_types( ty_fn_ptr_from, + *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, ) { diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 8da4d80badf..35d8e2573fe 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } -pub struct NllTypeRelating<'me, 'bccx, 'tcx> { +struct NllTypeRelating<'me, 'bccx, 'tcx> { type_checker: &'me mut TypeChecker<'bccx, 'tcx>, /// Where (and why) is this relation taking place? @@ -82,7 +82,7 @@ pub struct NllTypeRelating<'me, 'bccx, 'tcx> { } impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { - pub fn new( + fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 1ad80cb122a..2e41c918774 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -39,7 +39,7 @@ use crate::renumber::RegionCtxt; use crate::BorrowckInferCtxt; #[derive(Debug)] -pub struct UniversalRegions<'tcx> { +pub(crate) struct UniversalRegions<'tcx> { indices: UniversalRegionIndices<'tcx>, /// The vid assigned to `'static` @@ -95,7 +95,7 @@ pub struct UniversalRegions<'tcx> { /// regions appear free in the defining type and late-bound regions /// appear bound in the signature. #[derive(Copy, Clone, Debug)] -pub enum DefiningTy<'tcx> { +pub(crate) enum DefiningTy<'tcx> { /// The MIR is a closure. The signature is found via /// `ClosureArgs::closure_sig_ty`. Closure(DefId, GenericArgsRef<'tcx>), @@ -131,7 +131,7 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or coroutine, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> { + pub(crate) fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> { match self { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), @@ -145,7 +145,7 @@ impl<'tcx> DefiningTy<'tcx> { /// Number of implicit inputs -- notably the "environment" /// parameter for closures -- that appear in MIR but not in the /// user's code. - pub fn implicit_inputs(self) -> usize { + pub(crate) fn implicit_inputs(self) -> usize { match self { DefiningTy::Closure(..) | DefiningTy::CoroutineClosure(..) @@ -154,15 +154,15 @@ impl<'tcx> DefiningTy<'tcx> { } } - pub fn is_fn_def(&self) -> bool { + pub(crate) fn is_fn_def(&self) -> bool { matches!(*self, DefiningTy::FnDef(..)) } - pub fn is_const(&self) -> bool { + pub(crate) fn is_const(&self) -> bool { matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..)) } - pub fn def_id(&self) -> DefId { + pub(crate) fn def_id(&self) -> DefId { match *self { DefiningTy::Closure(def_id, ..) | DefiningTy::CoroutineClosure(def_id, ..) @@ -196,7 +196,7 @@ struct UniversalRegionIndices<'tcx> { } #[derive(Debug, PartialEq)] -pub enum RegionClassification { +pub(crate) enum RegionClassification { /// A **global** region is one that can be named from /// anywhere. There is only one, `'static`. Global, @@ -246,7 +246,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// MIR -- that is, all the regions that appear in the function's /// signature. This will also compute the relationships that are /// known between those regions. - pub fn new( + pub(crate) fn new( infcx: &BorrowckInferCtxt<'tcx>, mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, @@ -263,7 +263,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// if the `ClosureRegionRequirements` contains something like /// `'1: '2`, then the caller would impose the constraint that /// `V[1]: V[2]`. - pub fn closure_mapping( + pub(crate) fn closure_mapping( tcx: TyCtxt<'tcx>, closure_args: GenericArgsRef<'tcx>, expected_num_vars: usize, @@ -289,13 +289,13 @@ impl<'tcx> UniversalRegions<'tcx> { } /// Returns `true` if `r` is a member of this set of universal regions. - pub fn is_universal_region(&self, r: RegionVid) -> bool { + pub(crate) fn is_universal_region(&self, r: RegionVid) -> bool { (FIRST_GLOBAL_INDEX..self.num_universals).contains(&r.index()) } /// Classifies `r` as a universal region, returning `None` if this /// is not a member of this set of universal regions. - pub fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> { + pub(crate) fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> { let index = r.index(); if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(&index) { Some(RegionClassification::Global) @@ -310,17 +310,17 @@ impl<'tcx> UniversalRegions<'tcx> { /// Returns an iterator over all the RegionVids corresponding to /// universally quantified free regions. - pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> { + pub(crate) fn universal_regions(&self) -> impl Iterator<Item = RegionVid> { (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } /// Returns `true` if `r` is classified as a local region. - pub fn is_local_free_region(&self, r: RegionVid) -> bool { + pub(crate) fn is_local_free_region(&self, r: RegionVid) -> bool { self.region_classification(r) == Some(RegionClassification::Local) } /// Returns the number of universal regions created in any category. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.num_universals } @@ -329,19 +329,19 @@ impl<'tcx> UniversalRegions<'tcx> { /// closure type (versus those bound in the closure /// signature). They are therefore the regions between which the /// closure may impose constraints that its creator must verify. - pub fn num_global_and_external_regions(&self) -> usize { + pub(crate) fn num_global_and_external_regions(&self) -> usize { self.first_local_index } /// Gets an iterator over all the early-bound regions that have names. - pub fn named_universal_regions<'s>( + pub(crate) fn named_universal_regions<'s>( &'s self, ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's { self.indices.indices.iter().map(|(&r, &v)| (r, v)) } /// See `UniversalRegionIndices::to_region_vid`. - pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { self.indices.to_region_vid(r) } @@ -416,7 +416,7 @@ impl<'tcx> UniversalRegions<'tcx> { } } - pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> { + pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> { self.indices.tainted_by_errors.get() } } @@ -880,7 +880,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// reference those regions from the `ParamEnv`. It is also used /// during initialization. Relies on the `indices` map having been /// fully initialized. - pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { if let ty::ReVar(..) = *r { r.as_var() } else if let ty::ReError(guar) = *r { @@ -899,7 +899,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// Replaces all free regions in `value` with region vids, as /// returned by `to_region_vid`. - pub fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T + fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { diff --git a/compiler/rustc_borrowck/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs index 93c7810b545..55f1073176a 100644 --- a/compiler/rustc_borrowck/src/util/collect_writes.rs +++ b/compiler/rustc_borrowck/src/util/collect_writes.rs @@ -1,7 +1,7 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; -pub trait FindAssignments { +pub(crate) trait FindAssignments { // Finds all statements that assign directly to local (i.e., X = ...) // and returns their locations. fn find_assignments(&self, local: Local) -> Vec<Location>; diff --git a/compiler/rustc_borrowck/src/util/mod.rs b/compiler/rustc_borrowck/src/util/mod.rs index 7377d4de727..5f2960b768b 100644 --- a/compiler/rustc_borrowck/src/util/mod.rs +++ b/compiler/rustc_borrowck/src/util/mod.rs @@ -1,3 +1,3 @@ mod collect_writes; -pub use collect_writes::FindAssignments; +pub(crate) use collect_writes::FindAssignments; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c90a9164886..289e92a69b2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -351,15 +351,15 @@ struct TypeParameter { pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<P<Expr>>); impl BlockOrExpr { - pub fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr { + pub(crate) fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr { BlockOrExpr(stmts, None) } - pub fn new_expr(expr: P<Expr>) -> BlockOrExpr { + pub(crate) fn new_expr(expr: P<Expr>) -> BlockOrExpr { BlockOrExpr(ThinVec::new(), Some(expr)) } - pub fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr { + pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr { BlockOrExpr(stmts, expr) } @@ -461,7 +461,7 @@ fn find_type_parameters( } impl<'a> TraitDef<'a> { - pub fn expand( + pub(crate) fn expand( self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, @@ -471,7 +471,7 @@ impl<'a> TraitDef<'a> { self.expand_ext(cx, mitem, item, push, false); } - pub fn expand_ext( + pub(crate) fn expand_ext( self, cx: &ExtCtxt<'_>, mitem: &ast::MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 747da2ee43b..42855e255a8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -27,17 +27,17 @@ pub(crate) enum PathKind { } impl Path { - pub fn new(path: Vec<Symbol>) -> Path { + pub(crate) fn new(path: Vec<Symbol>) -> Path { Path::new_(path, Vec::new(), PathKind::Std) } - pub fn new_local(path: Symbol) -> Path { + pub(crate) fn new_local(path: Symbol) -> Path { Path::new_(vec![path], Vec::new(), PathKind::Local) } - pub fn new_(path: Vec<Symbol>, params: Vec<Box<Ty>>, kind: PathKind) -> Path { + pub(crate) fn new_(path: Vec<Symbol>, params: Vec<Box<Ty>>, kind: PathKind) -> Path { Path { path, params, kind } } - pub fn to_ty( + pub(crate) fn to_ty( &self, cx: &ExtCtxt<'_>, span: Span, @@ -46,7 +46,7 @@ impl Path { ) -> P<ast::Ty> { cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } - pub fn to_path( + pub(crate) fn to_path( &self, cx: &ExtCtxt<'_>, span: Span, @@ -87,7 +87,7 @@ pub(crate) fn self_ref() -> Ty { } impl Ty { - pub fn to_ty( + pub(crate) fn to_ty( &self, cx: &ExtCtxt<'_>, span: Span, @@ -108,7 +108,7 @@ impl Ty { } } - pub fn to_path( + pub(crate) fn to_path( &self, cx: &ExtCtxt<'_>, span: Span, @@ -167,10 +167,10 @@ pub(crate) struct Bounds { } impl Bounds { - pub fn empty() -> Bounds { + pub(crate) fn empty() -> Bounds { Bounds { bounds: Vec::new() } } - pub fn to_generics( + pub(crate) fn to_generics( &self, cx: &ExtCtxt<'_>, span: Span, diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index 7eb1f17a59c..c88c5bd35a5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -18,7 +18,7 @@ macro_rules! path { ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } } -pub fn expand_deriving_smart_ptr( +pub(crate) fn expand_deriving_smart_ptr( cx: &ExtCtxt<'_>, span: Span, _mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6ca43441e05..4fffffb91c8 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -930,7 +930,7 @@ pub(crate) struct ExpectedItem<'a> { #[derive(Diagnostic)] #[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] -pub struct NakedFunctionTestingAttribute { +pub(crate) struct NakedFunctionTestingAttribute { #[primary_span] #[label(builtin_macros_naked_attribute)] pub naked_span: Span, diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index b52f606f342..866ec72f116 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -5,7 +5,7 @@ pub(crate) mod printf { /// Represents a single `printf`-style substitution. #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { + pub(crate) enum Substitution<'a> { /// A formatted output substitution with its internal byte offset. Format(Format<'a>), /// A literal `%%` escape, with its start and end indices. @@ -13,21 +13,21 @@ pub(crate) mod printf { } impl<'a> Substitution<'a> { - pub fn as_str(&self) -> &str { + pub(crate) fn as_str(&self) -> &str { match self { Substitution::Format(fmt) => fmt.span, Substitution::Escape(_) => "%%", } } - pub fn position(&self) -> InnerSpan { + pub(crate) fn position(&self) -> InnerSpan { match self { Substitution::Format(fmt) => fmt.position, &Substitution::Escape((start, end)) => InnerSpan::new(start, end), } } - pub fn set_position(&mut self, start: usize, end: usize) { + pub(crate) fn set_position(&mut self, start: usize, end: usize) { match self { Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end), Substitution::Escape(pos) => *pos = (start, end), @@ -38,7 +38,7 @@ pub(crate) mod printf { /// /// This ignores cases where the substitution does not have an exact equivalent, or where /// the substitution would be unnecessary. - pub fn translate(&self) -> Result<String, Option<String>> { + pub(crate) fn translate(&self) -> Result<String, Option<String>> { match self { Substitution::Format(fmt) => fmt.translate(), Substitution::Escape(_) => Err(None), @@ -48,23 +48,23 @@ pub(crate) mod printf { #[derive(Clone, PartialEq, Debug)] /// A single `printf`-style formatting directive. - pub struct Format<'a> { + pub(crate) struct Format<'a> { /// The entire original formatting directive. - pub span: &'a str, + span: &'a str, /// The (1-based) parameter to be converted. - pub parameter: Option<u16>, + parameter: Option<u16>, /// Formatting flags. - pub flags: &'a str, + flags: &'a str, /// Minimum width of the output. - pub width: Option<Num>, + width: Option<Num>, /// Precision of the conversion. - pub precision: Option<Num>, + precision: Option<Num>, /// Length modifier for the conversion. - pub length: Option<&'a str>, + length: Option<&'a str>, /// Type of parameter being converted. - pub type_: &'a str, + type_: &'a str, /// Byte offset for the start and end of this formatting directive. - pub position: InnerSpan, + position: InnerSpan, } impl Format<'_> { @@ -72,7 +72,7 @@ pub(crate) mod printf { /// /// Returns `Err` in cases where the `printf` directive does not have an exact Rust /// equivalent, rather than guessing. - pub fn translate(&self) -> Result<String, Option<String>> { + pub(crate) fn translate(&self) -> Result<String, Option<String>> { use std::fmt::Write; let (c_alt, c_zero, c_left, c_plus) = { @@ -249,7 +249,7 @@ pub(crate) mod printf { /// A general number used in a `printf` formatting directive. #[derive(Copy, Clone, PartialEq, Debug)] - pub enum Num { + enum Num { // The range of these values is technically bounded by `NL_ARGMAX`... but, at least for GNU // libc, it apparently has no real fixed limit. A `u16` is used here on the basis that it // is *vanishingly* unlikely that *anyone* is going to try formatting something wider, or @@ -288,12 +288,12 @@ pub(crate) mod printf { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { + pub(crate) fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, pos: start_pos } } /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { + pub(crate) struct Substitutions<'a> { s: &'a str, pos: usize, } @@ -327,7 +327,7 @@ pub(crate) mod printf { } /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { + fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { use self::State::*; let at = { @@ -615,20 +615,20 @@ pub(crate) mod printf { mod tests; } -pub mod shell { +pub(crate) mod shell { use rustc_span::InnerSpan; use super::strcursor::StrCursor as Cur; #[derive(Clone, PartialEq, Debug)] - pub enum Substitution<'a> { + pub(crate) enum Substitution<'a> { Ordinal(u8, (usize, usize)), Name(&'a str, (usize, usize)), Escape((usize, usize)), } impl Substitution<'_> { - pub fn as_str(&self) -> String { + pub(crate) fn as_str(&self) -> String { match self { Substitution::Ordinal(n, _) => format!("${n}"), Substitution::Name(n, _) => format!("${n}"), @@ -636,17 +636,17 @@ pub mod shell { } } - pub fn position(&self) -> InnerSpan { + pub(crate) fn position(&self) -> InnerSpan { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; InnerSpan::new(pos.0, pos.1) } - pub fn set_position(&mut self, start: usize, end: usize) { + fn set_position(&mut self, start: usize, end: usize) { let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; *pos = (start, end); } - pub fn translate(&self) -> Result<String, Option<String>> { + pub(crate) fn translate(&self) -> Result<String, Option<String>> { match self { Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)), Substitution::Name(n, _) => Ok(format!("{{{}}}", n)), @@ -656,12 +656,12 @@ pub mod shell { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { + pub(crate) fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, pos: start_pos } } /// Iterator over substitutions in a string. - pub struct Substitutions<'a> { + pub(crate) struct Substitutions<'a> { s: &'a str, pos: usize, } @@ -683,7 +683,7 @@ pub mod shell { } /// Parse the next substitution from the input string. - pub fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { + fn parse_next_substitution(s: &str) -> Option<(Substitution<'_>, &str)> { let at = { let start = s.find('$')?; match s[start + 1..].chars().next()? { @@ -743,24 +743,24 @@ pub mod shell { } mod strcursor { - pub struct StrCursor<'a> { + pub(crate) struct StrCursor<'a> { s: &'a str, pub at: usize, } impl<'a> StrCursor<'a> { - pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { + pub(crate) fn new_at(s: &'a str, at: usize) -> StrCursor<'a> { StrCursor { s, at } } - pub fn at_next_cp(mut self) -> Option<StrCursor<'a>> { + pub(crate) fn at_next_cp(mut self) -> Option<StrCursor<'a>> { match self.try_seek_right_cp() { true => Some(self), false => None, } } - pub fn next_cp(mut self) -> Option<(char, StrCursor<'a>)> { + pub(crate) fn next_cp(mut self) -> Option<(char, StrCursor<'a>)> { let cp = self.cp_after()?; self.seek_right(cp.len_utf8()); Some((cp, self)) @@ -770,11 +770,11 @@ mod strcursor { &self.s[0..self.at] } - pub fn slice_after(&self) -> &'a str { + pub(crate) fn slice_after(&self) -> &'a str { &self.s[self.at..] } - pub fn slice_between(&self, until: StrCursor<'a>) -> Option<&'a str> { + pub(crate) fn slice_between(&self, until: StrCursor<'a>) -> Option<&'a str> { if !str_eq_literal(self.s, until.s) { None } else { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index a9ba7334d93..30e1c8d2622 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -16,6 +16,7 @@ #![feature(proc_macro_quote)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index ca910dccb0d..604a88393fd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -191,6 +191,14 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }) .try_into() .unwrap(), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(fx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap() + } _ => { fx.tcx.dcx().span_err( span, @@ -213,6 +221,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let total_len = lane_count * 2; + // FIXME: this is a terrible abstraction-breaking hack. + // Find a way to reuse `immediate_const_vector` from `codegen_ssa` instead. let indexes = { use rustc_middle::mir::interpret::*; let idx_const = match &idx.node { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 47b378cc1cd..6ba678e2e7c 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1923,15 +1923,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { v2: RValue<'gcc>, mask: RValue<'gcc>, ) -> RValue<'gcc> { - let struct_type = mask.get_type().is_struct().expect("mask should be of struct type"); - // TODO(antoyo): use a recursive unqualified() here. let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type"); let element_type = vector_type.get_element_type(); let vec_num_units = vector_type.get_num_units(); - let mask_num_units = struct_type.get_field_count(); - let mut vector_elements = vec![]; let mask_element_type = if element_type.is_integral() { element_type } else { @@ -1942,19 +1938,39 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] self.int_type }; - for i in 0..mask_num_units { - let field = struct_type.get_field(i as i32); - vector_elements.push(self.context.new_cast( - self.location, - mask.access_field(self.location, field).to_rvalue(), - mask_element_type, - )); - } + + let mut mask_elements = if let Some(vector_type) = mask.get_type().dyncast_vector() { + let mask_num_units = vector_type.get_num_units(); + let mut mask_elements = vec![]; + for i in 0..mask_num_units { + let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _); + mask_elements.push(self.context.new_cast( + self.location, + self.extract_element(mask, index).to_rvalue(), + mask_element_type, + )); + } + mask_elements + } else { + let struct_type = mask.get_type().is_struct().expect("mask should be of struct type"); + let mask_num_units = struct_type.get_field_count(); + let mut mask_elements = vec![]; + for i in 0..mask_num_units { + let field = struct_type.get_field(i as i32); + mask_elements.push(self.context.new_cast( + self.location, + mask.access_field(self.location, field).to_rvalue(), + mask_element_type, + )); + } + mask_elements + }; + let mask_num_units = mask_elements.len(); // NOTE: the mask needs to be the same length as the input vectors, so add the missing // elements in the mask if needed. for _ in mask_num_units..vec_num_units { - vector_elements.push(self.context.new_rvalue_zero(mask_element_type)); + mask_elements.push(self.context.new_rvalue_zero(mask_element_type)); } let result_type = self.context.new_vector_type(element_type, mask_num_units as u64); @@ -1998,7 +2014,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let new_mask_num_units = std::cmp::max(mask_num_units, vec_num_units); let mask_type = self.context.new_vector_type(mask_element_type, new_mask_num_units as u64); - let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements); + let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &mask_elements); let result = self.context.new_rvalue_vector_perm(self.location, v1, v2, mask); if vec_num_units != mask_num_units { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 8da1df3be15..96a833ccaf2 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -353,19 +353,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed + // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed // version of this intrinsic. - let n: u64 = match *args[2].layout.ty.kind() { + let idx_ty = args[2].layout.ty; + let n: u64 = match idx_ty.kind() { ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), }; require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 5ff580e295a..dea574a53cd 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -6,13 +6,13 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_middle::ty::layout::LayoutOf; -pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; +pub(crate) use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::Ty; use rustc_middle::{bug, ty}; use rustc_session::config; -pub use rustc_target::abi::call::*; +pub(crate) use rustc_target::abi::call::*; use rustc_target::abi::{self, HasDataLayout, Int, Size}; -pub use rustc_target::spec::abi::Abi; +pub(crate) use rustc_target::spec::abi::Abi; use rustc_target::spec::SanitizerSet; use smallvec::SmallVec; @@ -25,7 +25,7 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use crate::{attributes, llvm_util}; -pub trait ArgAttributesExt { +trait ArgAttributesExt { fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); fn apply_attrs_to_callsite( &self, @@ -111,7 +111,7 @@ impl ArgAttributesExt for ArgAttributes { } } -pub trait LlvmType { +pub(crate) trait LlvmType { fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } @@ -171,7 +171,7 @@ impl LlvmType for CastTarget { } } -pub trait ArgAbiExt<'ll, 'tcx> { +trait ArgAbiExt<'ll, 'tcx> { fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn store( &self, @@ -307,7 +307,7 @@ impl<'ll, 'tcx> ArgAbiMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } -pub trait FnAbiLlvmExt<'ll, 'tcx> { +pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index f931698c38f..1d91c3fb17d 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -913,8 +913,10 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty Primitive::Int(Integer::I16, _) => cx.type_i16(), Primitive::Int(Integer::I32, _) => cx.type_i32(), Primitive::Int(Integer::I64, _) => cx.type_i64(), + Primitive::Float(Float::F16) => cx.type_f16(), Primitive::Float(Float::F32) => cx.type_f32(), Primitive::Float(Float::F64) => cx.type_f64(), + Primitive::Float(Float::F128) => cx.type_f128(), // FIXME(erikdesjardins): handle non-default addrspace ptr sizes Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()), _ => unreachable!(), @@ -948,7 +950,9 @@ fn llvm_fixup_input<'ll, 'tcx>( value } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { let elem_ty = llvm_asm_scalar_type(bx.cx, s); let count = 16 / layout.size.bytes(); let vec_ty = bx.cx.type_vector(elem_ty, count); @@ -1090,7 +1094,9 @@ fn llvm_fixup_output<'ll, 'tcx>( value } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { value = bx.extract_element(value, bx.const_i32(0)); if let Primitive::Pointer(_) = s.primitive() { value = bx.inttoptr(value, layout.llvm_type(bx.cx)); @@ -1222,7 +1228,9 @@ fn llvm_fixup_output_type<'ll, 'tcx>( layout.llvm_type(cx) } } - (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => { + (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) + if s.primitive() != Primitive::Float(Float::F128) => + { let elem_ty = llvm_asm_scalar_type(cx, s); let count = 16 / layout.size.bytes(); cx.type_vector(elem_ty, count) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index fde95104093..92a857c2adc 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,6 +1,6 @@ //! Set and unset common attributes on LLVM values. -pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry}; @@ -17,13 +17,13 @@ use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace use crate::value::Value; use crate::{attributes, llvm_util}; -pub fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) { +pub(crate) fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) { if !attrs.is_empty() { llvm::AddFunctionAttributes(llfn, idx, attrs); } } -pub fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attribute]) { +pub(crate) fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attribute]) { if !attrs.is_empty() { llvm::AddCallSiteAttributes(callsite, idx, attrs); } @@ -80,7 +80,7 @@ fn patchable_function_entry_attrs<'ll>( /// Get LLVM sanitize attributes. #[inline] -pub fn sanitize_attrs<'ll>( +pub(crate) fn sanitize_attrs<'ll>( cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, ) -> SmallVec<[&'ll Attribute; 4]> { @@ -120,7 +120,7 @@ pub fn sanitize_attrs<'ll>( /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option<bool>) -> &Attribute { +pub(crate) fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option<bool>) -> &Attribute { // NOTE: We should determine if we even need async unwind tables, as they // take have more overhead and if we can use sync unwind tables we // probably should. @@ -128,7 +128,7 @@ pub fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option<bool>) -> &Att llvm::CreateUWTableAttr(llcx, async_unwind) } -pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { let mut fp = cx.sess().target.frame_pointer; let opts = &cx.sess().opts; // "mcount" function relies on stack pointer. @@ -280,19 +280,19 @@ fn backchain_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None } } -pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { +pub(crate) fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { let target_cpu = llvm_util::target_cpu(cx.tcx.sess); llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) } -pub fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { llvm_util::tune_cpu(cx.tcx.sess) .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu)) } /// Get the `NonLazyBind` LLVM attribute, /// if the codegen options allow skipping the PLT. -pub fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { +pub(crate) fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { // Don't generate calls through PLT if it's not necessary if !cx.sess().needs_plt() { Some(AttributeKind::NonLazyBind.create_attr(cx.llcx)) @@ -327,7 +327,7 @@ fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute { /// Helper for `FnAbi::apply_attrs_llfn`: /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. -pub fn llfn_attrs_from_instance<'ll, 'tcx>( +pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>, @@ -521,13 +521,20 @@ pub fn llfn_attrs_from_instance<'ll, 'tcx>( let function_features = function_features .iter() - .flat_map(|feat| { - llvm_util::to_llvm_features(cx.tcx.sess, feat).into_iter().map(|f| format!("+{f}")) - }) + // Convert to LLVMFeatures and filter out unavailable ones + .flat_map(|feat| llvm_util::to_llvm_features(cx.tcx.sess, feat)) + // Convert LLVMFeatures & dependencies to +<feats>s + .flat_map(|feat| feat.into_iter().map(|f| format!("+{f}"))) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) + // HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled + // It only exists as a feature in LLVM 18, cannot be passed down for any other version + .chain(match &*cx.tcx.sess.target.arch { + "aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()], + _ => vec![], + }) .collect::<Vec<String>>(); if cx.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index c0ec4f86b4d..4f2c83634a8 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -86,7 +86,7 @@ impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> { } } -pub struct LlvmArchiveBuilderBuilder; +pub(crate) struct LlvmArchiveBuilderBuilder; impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> { diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index aac446f3149..aa6842c75ce 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -33,9 +33,9 @@ use crate::{LlvmCodegenBackend, ModuleLlvm}; /// We keep track of the computed LTO cache keys from the previous /// session to determine which CGUs we can reuse. -pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; +const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; -pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { +fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { CrateType::Executable | CrateType::Dylib @@ -710,7 +710,7 @@ impl Drop for ThinBuffer { } } -pub unsafe fn optimize_thin_module( +pub(crate) unsafe fn optimize_thin_module( thin_module: ThinModule<LlvmCodegenBackend>, cgcx: &CodegenContext<LlvmCodegenBackend>, ) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> { @@ -806,7 +806,7 @@ pub unsafe fn optimize_thin_module( /// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys #[derive(Debug, Default)] -pub struct ThinLTOKeysMap { +struct ThinLTOKeysMap { // key = llvm name of importing module, value = LLVM cache key keys: BTreeMap<String, String>, } @@ -863,7 +863,7 @@ fn module_name_to_str(c_str: &CStr) -> &str { }) } -pub fn parse_module<'a>( +pub(crate) fn parse_module<'a>( cx: &'a llvm::Context, name: &CStr, data: &[u8], diff --git a/compiler/rustc_codegen_llvm/src/back/profiling.rs b/compiler/rustc_codegen_llvm/src/back/profiling.rs index 26fb4a96f84..79794775b7b 100644 --- a/compiler/rustc_codegen_llvm/src/back/profiling.rs +++ b/compiler/rustc_codegen_llvm/src/back/profiling.rs @@ -21,14 +21,14 @@ fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &st EventId::from_label(profiler.alloc_string(components.as_slice())) } -pub struct LlvmSelfProfiler<'a> { +pub(crate) struct LlvmSelfProfiler<'a> { profiler: Arc<SelfProfiler>, stack: Vec<TimingGuard<'a>>, llvm_pass_event_kind: StringId, } impl<'a> LlvmSelfProfiler<'a> { - pub fn new(profiler: Arc<SelfProfiler>) -> Self { + pub(crate) fn new(profiler: Arc<SelfProfiler>) -> Self { let llvm_pass_event_kind = profiler.alloc_string("LLVM Pass"); Self { profiler, stack: Vec::default(), llvm_pass_event_kind } } @@ -43,7 +43,7 @@ impl<'a> LlvmSelfProfiler<'a> { } } -pub unsafe extern "C" fn selfprofile_before_pass_callback( +pub(crate) unsafe extern "C" fn selfprofile_before_pass_callback( llvm_self_profiler: *mut c_void, pass_name: *const c_char, ir_name: *const c_char, @@ -56,7 +56,7 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback( } } -pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { +pub(crate) unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) }; llvm_self_profiler.after_pass_callback(); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 51b02891d02..adf7e933f43 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -43,14 +43,14 @@ use crate::llvm::{self, DiagnosticInfo, PassManager}; use crate::type_::Type; use crate::{base, common, llvm_util, LlvmCodegenBackend, ModuleLlvm}; -pub fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError { +pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError { match llvm::last_error() { Some(llvm_err) => dcx.emit_almost_fatal(WithLlvmError(err, llvm_err)), None => dcx.emit_almost_fatal(err), } } -pub fn write_output_file<'ll>( +fn write_output_file<'ll>( dcx: DiagCtxtHandle<'_>, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, @@ -95,7 +95,7 @@ pub fn write_output_file<'ll>( } } -pub fn create_informational_target_machine( +pub(crate) fn create_informational_target_machine( sess: &Session, only_base_features: bool, ) -> OwnedTargetMachine { @@ -107,7 +107,7 @@ pub fn create_informational_target_machine( .unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise()) } -pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { +pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { tcx.output_filenames(()).split_dwarf_path( tcx.sess.split_debuginfo(), @@ -130,9 +130,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMach .unwrap_or_else(|err| llvm_err(tcx.dcx(), err).raise()) } -pub fn to_llvm_opt_settings( - cfg: config::OptLevel, -) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) { +fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) { use self::config::OptLevel::*; match cfg { No => (llvm::CodeGenOptLevel::None, llvm::CodeGenOptSizeNone), @@ -179,7 +177,7 @@ pub(crate) fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeMod } } -pub fn target_machine_factory( +pub(crate) fn target_machine_factory( sess: &Session, optlvl: config::OptLevel, target_features: &[String], @@ -320,7 +318,7 @@ pub(crate) fn save_temp_bitcode( } /// In what context is a dignostic handler being attached to a codegen unit? -pub enum CodegenDiagnosticsStage { +pub(crate) enum CodegenDiagnosticsStage { /// Prelink optimization stage. Opt, /// LTO/ThinLTO postlink optimization stage. @@ -329,14 +327,14 @@ pub enum CodegenDiagnosticsStage { Codegen, } -pub struct DiagnosticHandlers<'a> { +pub(crate) struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'a>), llcx: &'a llvm::Context, old_handler: Option<&'a llvm::DiagnosticHandler>, } impl<'a> DiagnosticHandlers<'a> { - pub fn new( + pub(crate) fn new( cgcx: &'a CodegenContext<LlvmCodegenBackend>, dcx: DiagCtxtHandle<'a>, llcx: &'a llvm::Context, diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index e8236b45c89..0ba8d82406a 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -32,7 +32,7 @@ use crate::context::CodegenCx; use crate::value::Value; use crate::{attributes, llvm}; -pub struct ValueIter<'ll> { +pub(crate) struct ValueIter<'ll> { cur: Option<&'ll Value>, step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } @@ -49,11 +49,14 @@ impl<'ll> Iterator for ValueIter<'ll> { } } -pub fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { +pub(crate) fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal } } } -pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<ModuleLlvm>, u64) { +pub(crate) fn compile_codegen_unit( + tcx: TyCtxt<'_>, + cgu_name: Symbol, +) -> (ModuleCodegen<ModuleLlvm>, u64) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -140,7 +143,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen (module, cost) } -pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { +pub(crate) fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { let Some(sect) = attrs.link_section else { return }; unsafe { let buf = SmallCStr::new(sect.as_str()); @@ -148,7 +151,7 @@ pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { } } -pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { +pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { match linkage { Linkage::External => llvm::Linkage::ExternalLinkage, Linkage::AvailableExternally => llvm::Linkage::AvailableExternallyLinkage, @@ -164,7 +167,7 @@ pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { } } -pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { +pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { match linkage { Visibility::Default => llvm::Visibility::Default, Visibility::Hidden => llvm::Visibility::Hidden, diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index cc081f29e12..40783825cae 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -36,7 +36,7 @@ use crate::{attributes, llvm_util}; // All Builders must have an llfn associated with them #[must_use] -pub struct Builder<'a, 'll, 'tcx> { +pub(crate) struct Builder<'a, 'll, 'tcx> { pub llbuilder: &'ll mut llvm::Builder<'ll>, pub cx: &'a CodegenCx<'ll, 'tcx>, } @@ -1343,7 +1343,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Builder { llbuilder, cx } } - pub fn llfn(&self) -> &'ll Value { + pub(crate) fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } @@ -1375,7 +1375,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } - pub fn set_unpredictable(&mut self, inst: &'ll Value) { + pub(crate) fn set_unpredictable(&mut self, inst: &'ll Value) { unsafe { llvm::LLVMSetMetadata( inst, @@ -1385,15 +1385,15 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } - pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } } - pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + pub(crate) fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) } } - pub fn insert_element( + pub(crate) fn insert_element( &mut self, vec: &'ll Value, elt: &'ll Value, @@ -1402,7 +1402,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED) } } - pub fn shuffle_vector( + pub(crate) fn shuffle_vector( &mut self, v1: &'ll Value, v2: &'ll Value, @@ -1411,65 +1411,77 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED) } } - pub fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) } } - pub fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) } } - pub fn vector_reduce_fadd_reassoc(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fadd_reassoc( + &mut self, + acc: &'ll Value, + src: &'ll Value, + ) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); llvm::LLVMRustSetAllowReassoc(instr); instr } } - pub fn vector_reduce_fmul_reassoc(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmul_reassoc( + &mut self, + acc: &'ll Value, + src: &'ll Value, + ) -> &'ll Value { unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); llvm::LLVMRustSetAllowReassoc(instr); instr } } - pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) } } - pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) } } - pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) } } - pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) } } - pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } } - pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { + pub(crate) fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { + pub(crate) fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) } } - pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { + pub(crate) fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) } } - pub fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) { + pub(crate) fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) { unsafe { llvm::LLVMAddClause(landing_pad, clause); } } - pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { + pub(crate) fn catch_ret( + &mut self, + funclet: &Funclet<'ll>, + unwind: &'ll BasicBlock, + ) -> &'ll Value { let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } @@ -1515,7 +1527,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Cow::Owned(casted_args) } - pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { + pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 663c5be46e5..949fd1bc124 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -20,7 +20,7 @@ use crate::value::Value; /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { +pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { let tcx = cx.tcx(); debug!("get_fn(instance={:?})", instance); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a3997900184..ef6560ecbe5 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -13,7 +13,7 @@ use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer}; use tracing::debug; use crate::consts::const_alloc_to_llvm; -pub use crate::context::CodegenCx; +pub(crate) use crate::context::CodegenCx; use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True}; use crate::type_::Type; use crate::value::Value; @@ -58,21 +58,21 @@ use crate::value::Value; /// When inside of a landing pad, each function call in LLVM IR needs to be /// annotated with which landing pad it's a part of. This is accomplished via /// the `OperandBundleDef` value created for MSVC landing pads. -pub struct Funclet<'ll> { +pub(crate) struct Funclet<'ll> { cleanuppad: &'ll Value, operand: OperandBundleDef<'ll>, } impl<'ll> Funclet<'ll> { - pub fn new(cleanuppad: &'ll Value) -> Self { + pub(crate) fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) } } - pub fn cleanuppad(&self) -> &'ll Value { + pub(crate) fn cleanuppad(&self) -> &'ll Value { self.cleanuppad } - pub fn bundle(&self) -> &OperandBundleDef<'ll> { + pub(crate) fn bundle(&self) -> &OperandBundleDef<'ll> { &self.operand } } @@ -92,16 +92,16 @@ impl<'ll> BackendTypes for CodegenCx<'ll, '_> { } impl<'ll> CodegenCx<'ll, '_> { - pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { + pub(crate) fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow"); unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) } } - pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { + pub(crate) fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { bytes_in_context(self.llcx, bytes) } - pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { + pub(crate) fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow"); let r = llvm::LLVMGetAggregateElement(v, idx).unwrap(); @@ -339,18 +339,18 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } /// Get the [LLVM type][Type] of a [`Value`]. -pub fn val_ty(v: &Value) -> &Type { +pub(crate) fn val_ty(v: &Value) -> &Type { unsafe { llvm::LLVMTypeOf(v) } } -pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { +pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True) } } -pub fn struct_in_context<'ll>( +fn struct_in_context<'ll>( llcx: &'ll llvm::Context, elts: &[&'ll Value], packed: bool, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a764b263ec7..b143e28c5f9 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -29,7 +29,7 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use crate::{base, debuginfo}; -pub fn const_alloc_to_llvm<'ll>( +pub(crate) fn const_alloc_to_llvm<'ll>( cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>, is_static: bool, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 8862f139aff..01aae24ab56 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -11,6 +11,7 @@ use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, @@ -39,7 +40,7 @@ use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util}; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM /// `llvm::Context` so that several compilation units may be optimized in parallel. /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. -pub struct CodegenCx<'ll, 'tcx> { +pub(crate) struct CodegenCx<'ll, 'tcx> { pub tcx: TyCtxt<'tcx>, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, @@ -110,7 +111,7 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } -pub unsafe fn create_module<'ll>( +pub(crate) unsafe fn create_module<'ll>( tcx: TyCtxt<'_>, llcx: &'ll llvm::Context, mod_name: &str, @@ -226,6 +227,20 @@ pub unsafe fn create_module<'ll>( } } + // If we're normalizing integers with CFI, ensure LLVM generated functions do the same. + // See https://github.com/llvm/llvm-project/pull/104826 + if sess.is_sanitizer_cfi_normalize_integers_enabled() { + let cfi_normalize_integers = c"cfi-normalize-integers".as_ptr().cast(); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Override, + cfi_normalize_integers, + 1, + ); + } + } + // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.) if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() { let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr(); @@ -245,6 +260,22 @@ pub unsafe fn create_module<'ll>( unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); } + + // Add "kcfi-offset" module flag with -Z patchable-function-entry (See + // https://reviews.llvm.org/D141172). + let pfe = + PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry); + if pfe.prefix() > 0 { + let kcfi_offset = c"kcfi-offset".as_ptr().cast(); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Override, + kcfi_offset, + pfe.prefix().into(), + ); + } + } } // Control Flow Guard is currently only supported by the MSVC linker on Windows. @@ -531,7 +562,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } #[inline] - pub fn coverage_context(&self) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { + pub(crate) fn coverage_context( + &self, + ) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } @@ -1066,7 +1099,7 @@ impl<'ll> CodegenCx<'ll, '_> { impl CodegenCx<'_, '_> { /// Generates a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. - pub fn generate_local_symbol_name(&self, prefix: &str) -> String { + pub(crate) fn generate_local_symbol_name(&self, prefix: &str) -> String { let idx = self.local_gen_sym_counter.get(); self.local_gen_sym_counter.set(idx + 1); // Include a '.' character, so there can be no accidental conflicts with diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 584d033d6bd..d7a4f105f3c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::coverage::{ - CodeRegion, ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, + ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion, }; /// Must match the layout of `LLVMRustCounterKind`. @@ -80,7 +80,7 @@ pub struct CounterExpression { /// Must match the layout of `LLVMRustCounterMappingRegionKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub enum RegionKind { +enum RegionKind { /// A CodeRegion associates some code with a counter CodeRegion = 0, @@ -110,13 +110,13 @@ pub enum RegionKind { MCDCBranchRegion = 6, } -pub mod mcdc { +mod mcdc { use rustc_middle::mir::coverage::{ConditionInfo, DecisionInfo}; /// Must match the layout of `LLVMRustMCDCDecisionParameters`. #[repr(C)] #[derive(Clone, Copy, Debug, Default)] - pub struct DecisionParameters { + pub(crate) struct DecisionParameters { bitmap_idx: u32, num_conditions: u16, } @@ -127,14 +127,14 @@ pub mod mcdc { /// Must match the layout of `LLVMRustMCDCBranchParameters`. #[repr(C)] #[derive(Clone, Copy, Debug, Default)] - pub struct BranchParameters { + pub(crate) struct BranchParameters { condition_id: LLVMConditionId, condition_ids: [LLVMConditionId; 2], } #[repr(C)] #[derive(Clone, Copy, Debug)] - pub enum ParameterTag { + enum ParameterTag { None = 0, Decision = 1, Branch = 2, @@ -142,24 +142,24 @@ pub mod mcdc { /// Same layout with `LLVMRustMCDCParameters` #[repr(C)] #[derive(Clone, Copy, Debug)] - pub struct Parameters { + pub(crate) struct Parameters { tag: ParameterTag, decision_params: DecisionParameters, branch_params: BranchParameters, } impl Parameters { - pub fn none() -> Self { + pub(crate) fn none() -> Self { Self { tag: ParameterTag::None, decision_params: Default::default(), branch_params: Default::default(), } } - pub fn decision(decision_params: DecisionParameters) -> Self { + pub(crate) fn decision(decision_params: DecisionParameters) -> Self { Self { tag: ParameterTag::Decision, decision_params, branch_params: Default::default() } } - pub fn branch(branch_params: BranchParameters) -> Self { + pub(crate) fn branch(branch_params: BranchParameters) -> Self { Self { tag: ParameterTag::Branch, decision_params: Default::default(), branch_params } } } @@ -236,9 +236,10 @@ impl CounterMappingRegion { pub(crate) fn from_mapping( mapping_kind: &MappingKind, local_file_id: u32, - code_region: &CodeRegion, + source_region: &SourceRegion, ) -> Self { - let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = + source_region; match *mapping_kind { MappingKind::Code(term) => Self::code_region( Counter::from_term(term), diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 9433385c23a..5ed640b840e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -2,8 +2,8 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, - MappingKind, Op, + CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, + SourceRegion, }; use rustc_middle::ty::Instance; use rustc_span::Symbol; @@ -14,7 +14,7 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; /// Holds all of the coverage mapping data associated with a function instance, /// collected during traversal of `Coverage` statements in the function's MIR. #[derive(Debug)] -pub struct FunctionCoverageCollector<'tcx> { +pub(crate) struct FunctionCoverageCollector<'tcx> { /// Coverage info that was attached to this function by the instrumentor. function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, @@ -32,7 +32,7 @@ pub struct FunctionCoverageCollector<'tcx> { impl<'tcx> FunctionCoverageCollector<'tcx> { /// Creates a new set of coverage data for a used (called) function. - pub fn new( + pub(crate) fn new( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { @@ -40,7 +40,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { } /// Creates a new set of coverage data for an unused (never called) function. - pub fn unused( + pub(crate) fn unused( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, ) -> Self { @@ -195,13 +195,13 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Return the source hash, generated from the HIR node structure, and used to indicate whether /// or not the source code structure changed between different compilations. - pub fn source_hash(&self) -> u64 { + pub(crate) fn source_hash(&self) -> u64 { if self.is_used { self.function_coverage_info.function_source_hash } else { 0 } } /// Returns an iterator over all filenames used by this function's mappings. pub(crate) fn all_file_names(&self) -> impl Iterator<Item = Symbol> + Captures<'_> { - self.function_coverage_info.mappings.iter().map(|mapping| mapping.code_region.file_name) + self.function_coverage_info.mappings.iter().map(|mapping| mapping.source_region.file_name) } /// Convert this function's coverage expression data into a form that can be @@ -230,12 +230,12 @@ impl<'tcx> FunctionCoverage<'tcx> { /// that will be used by `mapgen` when preparing for FFI. pub(crate) fn counter_regions( &self, - ) -> impl Iterator<Item = (MappingKind, &CodeRegion)> + ExactSizeIterator { + ) -> impl Iterator<Item = (MappingKind, &SourceRegion)> + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let Mapping { kind, code_region } = mapping; + let Mapping { kind, source_region } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, code_region) + (kind, source_region) }) } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index f8929a26011..069b62af5e7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -27,7 +27,7 @@ use crate::{coverageinfo, llvm}; /// implementing this Rust version, and though the format documentation is very explicit and /// detailed, some undocumented details in Clang's implementation (that may or may not be important) /// were also replicated for Rust's Coverage Map. -pub fn finalize(cx: &CodegenCx<'_, '_>) { +pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; // Ensure that LLVM is using a version of the coverage mapping format that diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 20a713b8564..69babc7c9cf 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -22,10 +22,10 @@ use crate::llvm; pub(crate) mod ffi; pub(crate) mod map_data; -pub mod mapgen; +mod mapgen; /// A context object for maintaining all state needed by the coverageinfo module. -pub struct CrateCoverageContext<'ll, 'tcx> { +pub(crate) struct CrateCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, @@ -34,7 +34,7 @@ pub struct CrateCoverageContext<'ll, 'tcx> { } impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { function_coverage_map: Default::default(), pgo_func_name_var_map: Default::default(), @@ -42,7 +42,7 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } - pub fn take_function_coverage_map( + fn take_function_coverage_map( &self, ) -> FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> { self.function_coverage_map.replace(FxIndexMap::default()) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 0a02c230cfc..c3087d8ec30 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -15,7 +15,7 @@ use crate::llvm::debuginfo::{DILocation, DIScope}; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. -pub fn compute_mir_scopes<'ll, 'tcx>( +pub(crate) fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index e91bcea16a2..dc228e94811 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -16,7 +16,7 @@ use crate::value::Value; /// Inserts a side-effect free instruction sequence that makes sure that the /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. -pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { +pub(crate) fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { if needs_gdb_debug_scripts_section(bx) { let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx); // Load just the first byte as that's all that's necessary to force @@ -30,7 +30,9 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Value { +pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( + cx: &CodegenCx<'ll, '_>, +) -> &'ll Value { let c_section_var_name = c"__rustc_debug_gdb_scripts_section__"; let section_var_name = c_section_var_name.to_str().unwrap(); @@ -82,7 +84,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' }) } -pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { +pub(crate) fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { let omit_gdb_pretty_printer_section = attr::contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 30f90bada9a..dc59e9349b0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -85,7 +85,7 @@ const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<&'ll DIType> = | // SmallVec is used quite a bit in this module, so create a shorthand. // The actual number of elements is not so important. -pub type SmallVec<T> = smallvec::SmallVec<[T; 16]>; +type SmallVec<T> = smallvec::SmallVec<[T; 16]>; mod enums; mod type_map; @@ -425,7 +425,7 @@ fn build_slice_type_di_node<'ll, 'tcx>( /// /// This function will look up the debuginfo node in the TypeMap. If it can't find it, it /// will create the node by dispatching to the corresponding `build_*_di_node()` function. -pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t); if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) @@ -531,7 +531,7 @@ fn hex_encode(data: &[u8]) -> String { hex_string } -pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { +pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { let cache_key = Some((source_file.stable_id, source_file.src_hash)); return debug_context(cx) .created_files @@ -629,6 +629,9 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> }; let hash_value = hex_encode(source_file.src_hash.hash_bytes()); + let source = + cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); + unsafe { llvm::LLVMRustDIBuilderCreateFile( DIB(cx), @@ -639,12 +642,14 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> hash_kind, hash_value.as_ptr().cast(), hash_value.len(), + source.map_or(ptr::null(), |x| x.as_ptr().cast()), + source.map_or(0, |x| x.len()), ) } } } -pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { +fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| unsafe { let file_name = "<unknown>"; let directory = ""; @@ -659,6 +664,8 @@ pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { llvm::ChecksumKind::None, hash_value.as_ptr().cast(), hash_value.len(), + ptr::null(), + 0, ) }) } @@ -859,7 +866,7 @@ fn build_param_type_di_node<'ll, 'tcx>( } } -pub fn build_compile_unit_di_node<'ll, 'tcx>( +pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( tcx: TyCtxt<'tcx>, codegen_unit_name: &str, debug_context: &CodegenUnitDebugContext<'ll, 'tcx>, @@ -943,6 +950,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( llvm::ChecksumKind::None, ptr::null(), 0, + ptr::null(), + 0, ); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( @@ -1319,7 +1328,11 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( /// Creates debug information for the given global variable. /// /// Adds the created debuginfo nodes directly to the crate's IR. -pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { +pub(crate) fn build_global_var_di_node<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1559,7 +1572,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_di_node<'ll, 'tcx>( +pub(crate) fn create_vtable_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, @@ -1604,7 +1617,7 @@ pub fn create_vtable_di_node<'ll, 'tcx>( } /// Creates an "extension" of an existing `DIScope` into another file. -pub fn extend_scope_to_file<'ll>( +pub(crate) fn extend_scope_to_file<'ll>( cx: &CodegenCx<'ll, '_>, scope_metadata: &'ll DIScope, file: &SourceFile, @@ -1613,7 +1626,7 @@ pub fn extend_scope_to_file<'ll>( unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) } } -pub fn tuple_field_name(field_index: usize) -> Cow<'static, str> { +fn tuple_field_name(field_index: usize) -> Cow<'static, str> { const TUPLE_FIELD_NAMES: [&'static str; 16] = [ "__0", "__1", "__2", "__3", "__4", "__5", "__6", "__7", "__8", "__9", "__10", "__11", "__12", "__13", "__14", "__15", diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 77cbcd86cdd..edaf73b74a2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -257,7 +257,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( /// ---> DW_TAG_structure_type (type of variant 3) /// /// ``` -pub fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( +fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, variant_index: VariantIdx, coroutine_type_and_layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 25b2df9c52c..6d21f4204e3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -22,7 +22,7 @@ mod private { // `UniqueTypeId` from being constructed directly, without asserting // the preconditions. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, HashStable)] - pub struct HiddenZst; + pub(crate) struct HiddenZst; } /// A unique identifier for anything that we create a debuginfo node for. @@ -48,17 +48,17 @@ pub(super) enum UniqueTypeId<'tcx> { } impl<'tcx> UniqueTypeId<'tcx> { - pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { + pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); UniqueTypeId::Ty(t, private::HiddenZst) } - pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { + pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); UniqueTypeId::VariantPart(enum_ty, private::HiddenZst) } - pub fn for_enum_variant_struct_type( + pub(crate) fn for_enum_variant_struct_type( tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>, variant_idx: VariantIdx, @@ -67,7 +67,7 @@ impl<'tcx> UniqueTypeId<'tcx> { UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } - pub fn for_enum_variant_struct_type_wrapper( + pub(crate) fn for_enum_variant_struct_type_wrapper( tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>, variant_idx: VariantIdx, @@ -76,7 +76,7 @@ impl<'tcx> UniqueTypeId<'tcx> { UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) } - pub fn for_vtable_ty( + pub(crate) fn for_vtable_ty( tcx: TyCtxt<'tcx>, self_type: Ty<'tcx>, implemented_trait: Option<PolyExistentialTraitRef<'tcx>>, @@ -93,7 +93,7 @@ impl<'tcx> UniqueTypeId<'tcx> { /// argument of the various `LLVMRustDIBuilderCreate*Type()` methods. /// /// Right now this takes the form of a hex-encoded opaque hash value. - pub fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { + fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String { let mut hasher = StableHasher::new(); tcx.with_stable_hashing_context(|mut hcx| { hcx.while_hashing_spans(false, |hcx| self.hash_stable(hcx, &mut hasher)) @@ -101,7 +101,7 @@ impl<'tcx> UniqueTypeId<'tcx> { hasher.finish::<Fingerprint>().to_hex() } - pub fn expect_ty(self) -> Ty<'tcx> { + pub(crate) fn expect_ty(self) -> Ty<'tcx> { match self { UniqueTypeId::Ty(ty, _) => ty, _ => bug!("Expected `UniqueTypeId::Ty` but found `{:?}`", self), @@ -133,25 +133,25 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { } } -pub struct DINodeCreationResult<'ll> { +pub(crate) struct DINodeCreationResult<'ll> { pub di_node: &'ll DIType, pub already_stored_in_typemap: bool, } impl<'ll> DINodeCreationResult<'ll> { - pub fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self { + pub(crate) fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self { DINodeCreationResult { di_node, already_stored_in_typemap } } } #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum Stub<'ll> { +pub(crate) enum Stub<'ll> { Struct, Union, VTableTy { vtable_holder: &'ll DIType }, } -pub struct StubInfo<'ll, 'tcx> { +pub(crate) struct StubInfo<'ll, 'tcx> { metadata: &'ll DIType, unique_type_id: UniqueTypeId<'tcx>, } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index eb446d2d7b2..f5d6fc6f080 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -40,13 +40,13 @@ use crate::llvm::debuginfo::{ use crate::value::Value; mod create_scope_map; -pub mod gdb; -pub mod metadata; +mod gdb; +pub(crate) mod metadata; mod namespace; mod utils; -pub use self::create_scope_map::compute_mir_scopes; -pub use self::metadata::build_global_var_di_node; +use self::create_scope_map::compute_mir_scopes; +pub(crate) use self::metadata::build_global_var_di_node; #[allow(non_upper_case_globals)] const DW_TAG_auto_variable: c_uint = 0x100; @@ -54,7 +54,7 @@ const DW_TAG_auto_variable: c_uint = 0x100; const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. -pub struct CodegenUnitDebugContext<'ll, 'tcx> { +pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { llcontext: &'ll llvm::Context, llmod: &'ll llvm::Module, builder: &'ll mut DIBuilder<'ll>, @@ -74,7 +74,7 @@ impl Drop for CodegenUnitDebugContext<'_, '_> { } impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { - pub fn new(llmod: &'ll llvm::Module) -> Self { + pub(crate) fn new(llmod: &'ll llvm::Module) -> Self { debug!("CodegenUnitDebugContext::new"); let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one @@ -90,7 +90,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { } } - pub fn finalize(&self, sess: &Session) { + pub(crate) fn finalize(&self, sess: &Session) { unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder); @@ -134,7 +134,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { } /// Creates any deferred debug metadata nodes -pub fn finalize(cx: &CodegenCx<'_, '_>) { +pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { if let Some(dbg_cx) = &cx.dbg_cx { debug!("finalize"); @@ -241,13 +241,13 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { // FIXME(eddyb) rename this to better indicate it's a duplicate of // `rustc_span::Loc` rather than `DILocation`, perhaps by making // `lookup_char_pos` return the right information instead. -pub struct DebugLoc { +struct DebugLoc { /// Information about the original source file. - pub file: Lrc<SourceFile>, + file: Lrc<SourceFile>, /// The (1-based) line number. - pub line: u32, + line: u32, /// The (1-based) column number. - pub col: u32, + col: u32, } impl CodegenCx<'_, '_> { @@ -255,7 +255,7 @@ impl CodegenCx<'_, '_> { // FIXME(eddyb) rename this to better indicate it's a duplicate of // `lookup_char_pos` rather than `dbg_loc`, perhaps by making // `lookup_char_pos` return the right information instead. - pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { + fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { let (file, line, col) = match self.sess().source_map().lookup_line(pos) { Ok(SourceFileAndLine { sf: file, line }) => { let line_pos = file.lines()[line]; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 5c4f8fe99e3..83d7a82dadc 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -9,7 +9,7 @@ use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::DIScope; -pub fn mangled_name_of_instance<'a, 'tcx>( +pub(crate) fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>, ) -> ty::SymbolName<'tcx> { @@ -17,7 +17,7 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index e542aa96e8a..321553a3df0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -11,7 +11,7 @@ use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope}; -pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { +pub(crate) fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { // The is_local_to_unit flag indicates whether a function is local to the // current compilation unit (i.e., if it is *static* in the C-sense). The // *reachable* set should provide a good approximation of this, as it @@ -24,7 +24,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { } #[allow(non_snake_case)] -pub fn create_DIArray<'ll>( +pub(crate) fn create_DIArray<'ll>( builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>], ) -> &'ll DIArray { @@ -32,7 +32,7 @@ pub fn create_DIArray<'ll>( } #[inline] -pub fn debug_context<'a, 'll, 'tcx>( +pub(crate) fn debug_context<'a, 'll, 'tcx>( cx: &'a CodegenCx<'ll, 'tcx>, ) -> &'a CodegenUnitDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() @@ -40,11 +40,11 @@ pub fn debug_context<'a, 'll, 'tcx>( #[inline] #[allow(non_snake_case)] -pub fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { +pub(crate) fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id)) } diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 2aa349b2782..4e4500b6373 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -65,7 +65,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// return its Value instead. - pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { + pub(crate) fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } } @@ -77,7 +77,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_cfn( + pub(crate) fn declare_cfn( &self, name: &str, unnamed: llvm::UnnamedAddr, @@ -100,7 +100,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_entry_fn( + pub(crate) fn declare_entry_fn( &self, name: &str, callconv: llvm::CallConv, @@ -119,7 +119,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - pub fn declare_fn( + pub(crate) fn declare_fn( &self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, @@ -199,7 +199,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// return `None` if the name already has a definition associated with it. In that /// case an error should be reported to the user, because it usually happens due /// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes). - pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { + pub(crate) fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { if self.get_defined_value(name).is_some() { None } else { @@ -210,19 +210,19 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Declare a private global /// /// Use this function when you intend to define a global without a name. - pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { + pub(crate) fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) } } /// Gets declared value by name. - pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { + pub(crate) fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) } } /// Gets defined or externally defined (AvailableExternally linkage) value by /// name. - pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { + pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { self.get_declared_value(name).and_then(|val| { let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 }; if !declaration { Some(val) } else { None } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index e0ec9cdca56..bb481d2a308 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -207,13 +207,13 @@ pub(crate) struct CopyBitcode { #[derive(Diagnostic)] #[diag(codegen_llvm_unknown_debuginfo_compression)] -pub struct UnknownCompression { +pub(crate) struct UnknownCompression { pub algorithm: &'static str, } #[derive(Diagnostic)] #[diag(codegen_llvm_mismatch_data_layout)] -pub struct MismatchedDataLayout<'a> { +pub(crate) struct MismatchedDataLayout<'a> { pub rustc_target: &'a str, pub rustc_layout: &'a str, pub llvm_target: &'a str, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index abfe38d4c0c..a300f5f707a 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1287,19 +1287,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } if name == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed + // Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed // version of this intrinsic. - let n: u64 = match args[2].layout.ty.kind() { + let idx_ty = args[2].layout.ty; + let n: u64 = match idx_ty.kind() { ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + _ if idx_ty.is_simd() + && matches!( + idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(), + ty::Uint(ty::UintTy::U32) + ) => + { + idx_ty.simd_size_and_type(bx.cx.tcx).0 + } + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }), }; let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 43164390a1c..6a303e1e602 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,6 +6,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -16,6 +17,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::any::Any; @@ -45,11 +47,11 @@ use rustc_session::Session; use rustc_span::symbol::Symbol; mod back { - pub mod archive; - pub mod lto; - pub mod owned_target_machine; + pub(crate) mod archive; + pub(crate) mod lto; + pub(crate) mod owned_target_machine; mod profiling; - pub mod write; + pub(crate) mod write; } mod abi; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index faabbcb020d..5e0d7418993 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -564,12 +564,12 @@ pub enum ArchiveKind { } // LLVMRustThinLTOData -extern "C" { +unsafe extern "C" { pub type ThinLTOData; } // LLVMRustThinLTOBuffer -extern "C" { +unsafe extern "C" { pub type ThinLTOBuffer; } @@ -621,7 +621,7 @@ pub enum MemoryEffects { InaccessibleMemOnly, } -extern "C" { +unsafe extern "C" { type Opaque; } #[repr(C)] @@ -631,54 +631,54 @@ struct InvariantOpaque<'a> { } // Opaque pointer types -extern "C" { +unsafe extern "C" { pub type Module; } -extern "C" { +unsafe extern "C" { pub type Context; } -extern "C" { +unsafe extern "C" { pub type Type; } -extern "C" { +unsafe extern "C" { pub type Value; } -extern "C" { +unsafe extern "C" { pub type ConstantInt; } -extern "C" { +unsafe extern "C" { pub type Attribute; } -extern "C" { +unsafe extern "C" { pub type Metadata; } -extern "C" { +unsafe extern "C" { pub type BasicBlock; } #[repr(C)] pub struct Builder<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct PassManager<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type Pass; } -extern "C" { +unsafe extern "C" { pub type TargetMachine; } -extern "C" { +unsafe extern "C" { pub type Archive; } #[repr(C)] pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct ArchiveChild<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type Twine; } -extern "C" { +unsafe extern "C" { pub type DiagnosticInfo; } -extern "C" { +unsafe extern "C" { pub type SMDiagnostic; } #[repr(C)] @@ -688,7 +688,7 @@ pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct Linker<'a>(InvariantOpaque<'a>); -extern "C" { +unsafe extern "C" { pub type DiagnosticHandler; } @@ -823,7 +823,7 @@ bitflags! { } } -extern "C" { +unsafe extern "C" { pub type ModuleBuffer; } @@ -834,7 +834,7 @@ pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; -extern "C" { +unsafe extern "C" { // Create and destroy contexts. pub fn LLVMContextDispose(C: &'static mut Context); pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; @@ -1518,7 +1518,7 @@ extern "C" { } #[link(name = "llvm-wrapper", kind = "static")] -extern "C" { +unsafe extern "C" { pub fn LLVMRustInstallErrorHandlers(); pub fn LLVMRustDisableSystemDialogsOnCrash(); @@ -1860,6 +1860,8 @@ extern "C" { CSKind: ChecksumKind, Checksum: *const c_char, ChecksumLen: size_t, + Source: *const c_char, + SourceLen: size_t, ) -> &'a DIFile; pub fn LLVMRustDIBuilderCreateSubroutineType<'a>( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9fd8ca43789..618602ed70f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -136,14 +136,14 @@ unsafe fn configure_llvm(sess: &Session) { unsafe { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()) }; } -pub fn time_trace_profiler_finish(file_name: &Path) { +pub(crate) fn time_trace_profiler_finish(file_name: &Path) { unsafe { let file_name = path_to_c_string(file_name); llvm::LLVMRustTimeTraceProfilerFinish(file_name.as_ptr()); } } -pub enum TargetFeatureFoldStrength<'a> { +enum TargetFeatureFoldStrength<'a> { // The feature is only tied when enabling the feature, disabling // this feature shouldn't disable the tied feature. EnableOnly(&'a str), @@ -160,28 +160,28 @@ impl<'a> TargetFeatureFoldStrength<'a> { } } -pub struct LLVMFeature<'a> { - pub llvm_feature_name: &'a str, - pub dependency: Option<TargetFeatureFoldStrength<'a>>, +pub(crate) struct LLVMFeature<'a> { + llvm_feature_name: &'a str, + dependency: Option<TargetFeatureFoldStrength<'a>>, } impl<'a> LLVMFeature<'a> { - pub fn new(llvm_feature_name: &'a str) -> Self { + fn new(llvm_feature_name: &'a str) -> Self { Self { llvm_feature_name, dependency: None } } - pub fn with_dependency( + fn with_dependency( llvm_feature_name: &'a str, dependency: TargetFeatureFoldStrength<'a>, ) -> Self { Self { llvm_feature_name, dependency: Some(dependency) } } - pub fn contains(&self, feat: &str) -> bool { + fn contains(&self, feat: &str) -> bool { self.iter().any(|dep| dep == feat) } - pub fn iter(&'a self) -> impl Iterator<Item = &'a str> { + fn iter(&'a self) -> impl Iterator<Item = &'a str> { let dependencies = self.dependency.iter().map(|feat| feat.as_str()); std::iter::once(self.llvm_feature_name).chain(dependencies) } @@ -209,7 +209,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { +pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFeature<'a>> { let arch = if sess.target.arch == "x86_64" { "x86" } else if sess.target.arch == "arm64ec" { @@ -218,46 +218,65 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { &*sess.target.arch }; match (arch, s) { - ("x86", "sse4.2") => { - LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) - } - ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"), - ("x86", "rdrand") => LLVMFeature::new("rdrnd"), - ("x86", "bmi1") => LLVMFeature::new("bmi"), - ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"), - ("x86", "lahfsahf") => LLVMFeature::new("sahf"), - ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"), - ("aarch64", "dpb") => LLVMFeature::new("ccpp"), - ("aarch64", "dpb2") => LLVMFeature::new("ccdp"), - ("aarch64", "frintts") => LLVMFeature::new("fptoint"), - ("aarch64", "fcma") => LLVMFeature::new("complxnum"), - ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"), - ("aarch64", "paca") => LLVMFeature::new("pauth"), - ("aarch64", "pacg") => LLVMFeature::new("pauth"), + ("x86", "sse4.2") => Some(LLVMFeature::with_dependency( + "sse4.2", + TargetFeatureFoldStrength::EnableOnly("crc32"), + )), + ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")), + ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")), + ("x86", "bmi1") => Some(LLVMFeature::new("bmi")), + ("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")), + ("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")), + ("aarch64", "rcpc2") => Some(LLVMFeature::new("rcpc-immo")), + ("aarch64", "dpb") => Some(LLVMFeature::new("ccpp")), + ("aarch64", "dpb2") => Some(LLVMFeature::new("ccdp")), + ("aarch64", "frintts") => Some(LLVMFeature::new("fptoint")), + ("aarch64", "fcma") => Some(LLVMFeature::new("complxnum")), + ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")), + ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), + ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), + ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { - LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")) + Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))) } // In LLVM neon implicitly enables fp, but we manually enable // neon when a feature only implicitly enables fp - ("aarch64", "fhm") => LLVMFeature::new("fp16fml"), - ("aarch64", "fp16") => LLVMFeature::new("fullfp16"), + ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")), + ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), + // Filter out features that are not supported by the current LLVM version + ("aarch64", "faminmax") if get_version().0 < 18 => None, + ("aarch64", "fp8") if get_version().0 < 18 => None, + ("aarch64", "fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "fp8fma") if get_version().0 < 18 => None, + ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("aarch64", "lut") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f16") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f32") if get_version().0 < 18 => None, + ("aarch64", "sme-fa64") if get_version().0 < 18 => None, + ("aarch64", "sme-lutv2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8fma") if get_version().0 < 18 => None, + ("aarch64", "v9.5a") if get_version().0 < 18 => None, // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called // `fast-unaligned-access`. In LLVM 19, it was split back out. ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { - LLVMFeature::new("fast-unaligned-access") + Some(LLVMFeature::new("fast-unaligned-access")) } // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled. ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => { - LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")) + Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) } - (_, s) => LLVMFeature::new(s), + (_, s) => Some(LLVMFeature::new(s)), } } /// Given a map from target_features to whether they are enabled or disabled, /// ensure only valid combinations are allowed. -pub fn check_tied_features( +pub(crate) fn check_tied_features( sess: &Session, features: &FxHashMap<&str, bool>, ) -> Option<&'static [&'static str]> { @@ -291,13 +310,17 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { return true; } // check that all features in a given smallvec are enabled - for llvm_feature in to_llvm_features(sess, feature) { - let cstr = SmallCStr::new(llvm_feature); - if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { - return false; + if let Some(feat) = to_llvm_features(sess, feature) { + for llvm_feature in feat { + let cstr = SmallCStr::new(llvm_feature); + if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { + return false; + } } + true + } else { + false } - true }) .map(|(feature, _, _)| Symbol::intern(feature)), ); @@ -337,19 +360,19 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { .collect() } -pub fn print_version() { +pub(crate) fn print_version() { let (major, minor, patch) = get_version(); println!("LLVM version: {major}.{minor}.{patch}"); } -pub fn get_version() -> (u32, u32, u32) { +pub(crate) fn get_version() -> (u32, u32, u32) { // Can be called without initializing LLVM unsafe { (llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor(), llvm::LLVMRustVersionPatch()) } } -pub fn print_passes() { +pub(crate) fn print_passes() { // Can be called without initializing LLVM unsafe { llvm::LLVMRustPrintPasses(); @@ -386,9 +409,9 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach .target .supported_target_features() .iter() - .map(|(feature, _gate, _implied)| { + .filter_map(|(feature, _gate, _implied)| { // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name; + let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; let desc = match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() { Some(index) => { @@ -398,7 +421,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach None => "", }; - (*feature, desc) + Some((*feature, desc)) }) .collect::<Vec<_>>(); @@ -479,7 +502,7 @@ fn handle_native(name: &str) -> &str { } } -pub fn target_cpu(sess: &Session) -> &str { +pub(crate) fn target_cpu(sess: &Session) -> &str { match sess.opts.cg.target_cpu { Some(ref name) => handle_native(name), None => handle_native(sess.target.cpu.as_ref()), @@ -595,7 +618,7 @@ pub(crate) fn global_llvm_features( if feature_state.is_none() { let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature); + let llvm_features = to_llvm_features(sess, rust_feature)?; if llvm_features.contains(feature) && !llvm_features.contains(rust_feature) { @@ -641,7 +664,7 @@ pub(crate) fn global_llvm_features( // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - let llvm_feature = to_llvm_features(sess, feature); + let llvm_feature = to_llvm_features(sess, feature)?; Some( std::iter::once(format!( @@ -691,6 +714,9 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { let feature = s .strip_prefix(&['+', '-'][..]) .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); + if s.is_empty() { + return None; + } // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { @@ -699,7 +725,7 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { Some(feature) } -pub fn tune_cpu(sess: &Session) -> Option<&str> { +pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 7e3ab19898d..ec1e2cb8094 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -12,7 +12,7 @@ use rustc_target::abi::{AddressSpace, Align, Integer, Size}; use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::context::CodegenCx; -pub use crate::llvm::Type; +pub(crate) use crate::llvm::Type; use crate::llvm::{Bool, False, True}; use crate::type_of::LayoutLlvmExt; use crate::value::Value; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 4755fa08afb..6e429a1674a 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -139,21 +139,21 @@ fn struct_llfields<'a, 'tcx>( } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn align_of(&self, ty: Ty<'tcx>) -> Align { + pub(crate) fn align_of(&self, ty: Ty<'tcx>) -> Align { self.layout_of(ty).align.abi } - pub fn size_of(&self, ty: Ty<'tcx>) -> Size { + pub(crate) fn size_of(&self, ty: Ty<'tcx>) -> Size { self.layout_of(ty).size } - pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { + pub(crate) fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) { let layout = self.layout_of(ty); (layout.size, layout.align.abi) } } -pub trait LayoutLlvmExt<'tcx> { +pub(crate) trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; fn is_llvm_scalar_pair(&self) -> bool; fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; diff --git a/compiler/rustc_codegen_llvm/src/value.rs b/compiler/rustc_codegen_llvm/src/value.rs index 6295b0de356..2eabac3be8c 100644 --- a/compiler/rustc_codegen_llvm/src/value.rs +++ b/compiler/rustc_codegen_llvm/src/value.rs @@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher}; use std::{fmt, ptr}; use crate::llvm; -pub use crate::llvm::Value; +pub(crate) use crate::llvm::Value; impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index e3033b332ca..e78039bafd8 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -5,10 +5,10 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -ar_archive_writer = "0.4.0" +ar_archive_writer = "0.4.2" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" -cc = "1.0.90" +cc = "=1.0.105" # FIXME(cc): pinned to keep support for VS2013 either = "1.5.0" itertools = "0.12" jobserver = "0.1.28" diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 38a440a707a..76a94de5433 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -108,7 +108,11 @@ pub trait ArchiveBuilderBuilder { &exports, machine, !sess.target.is_like_msvc, - /*comdat=*/ false, + // Enable compatibility with MSVC's `/WHOLEARCHIVE` flag. + // Without this flag a duplicate symbol error would be emitted + // when linking a rust staticlib using `/WHOLEARCHIVE`. + // See #129020 + true, ) { sess.dcx() .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }); @@ -121,7 +125,7 @@ pub trait ArchiveBuilderBuilder { rlib: &'a Path, outdir: &Path, bundled_lib_file_names: &FxIndexSet<Symbol>, - ) -> Result<(), ExtractBundledLibsError<'_>> { + ) -> Result<(), ExtractBundledLibsError<'a>> { let archive_map = unsafe { Mmap::map( File::open(rlib) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7bad9d33e7d..4d19425255f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1207,7 +1207,7 @@ mod win { /// Get the Windows system OEM code page. This is most notably the code page /// used for link.exe's output. - pub fn oem_code_page() -> u32 { + pub(super) fn oem_code_page() -> u32 { unsafe { let mut cp: u32 = 0; // We're using the `LOCALE_RETURN_NUMBER` flag to return a u32. @@ -1230,7 +1230,7 @@ mod win { /// /// It will fail if the multi-byte string is longer than `i32::MAX` or if it contains /// any invalid bytes for the expected encoding. - pub fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option<String> { + pub(super) fn locale_byte_str_to_string(s: &[u8], code_page: u32) -> Option<String> { // `MultiByteToWideChar` requires a length to be a "positive integer". if s.len() > isize::MAX as usize { return None; @@ -1317,11 +1317,9 @@ fn link_sanitizer_runtime( name: &str, ) { fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf { - let session_tlib = - filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple()); - let path = session_tlib.join(filename); + let path = sess.target_tlib_path.dir.join(filename); if path.exists() { - return session_tlib; + return sess.target_tlib_path.dir.clone(); } else { let default_sysroot = filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); @@ -1612,19 +1610,18 @@ fn print_native_static_libs( } fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf { - let fs = sess.target_filesearch(PathKind::Native); - let file_path = fs.get_lib_path().join(name); + let file_path = sess.target_tlib_path.dir.join(name); if file_path.exists() { return file_path; } // Special directory with objects used only in self-contained linkage mode if self_contained { - let file_path = fs.get_self_contained_lib_path().join(name); + let file_path = sess.target_tlib_path.dir.join("self-contained").join(name); if file_path.exists() { return file_path; } } - for search_path in fs.search_paths() { + for search_path in sess.target_filesearch(PathKind::Native).search_paths() { let file_path = search_path.dir.join(name); if file_path.exists() { return file_path; @@ -2131,7 +2128,7 @@ fn add_library_search_dirs( | LinkSelfContainedComponents::UNWIND | LinkSelfContainedComponents::MINGW, ) { - let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path(); + let lib_path = sess.target_tlib_path.dir.join("self-contained"); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } @@ -2146,8 +2143,7 @@ fn add_library_search_dirs( || sess.target.os == "fuchsia" || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { - let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + cmd.include_path(&fix_windows_verbatim_for_gcc(&sess.target_tlib_path.dir)); } // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks @@ -2859,15 +2855,14 @@ fn add_upstream_native_libraries( // // The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it. fn rehome_sysroot_lib_dir(sess: &Session, lib_dir: &Path) -> PathBuf { - let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); + let sysroot_lib_path = &sess.target_tlib_path.dir; let canonical_sysroot_lib_path = - { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; + { try_canonicalize(sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf()); if canonical_lib_dir == canonical_sysroot_lib_path { - // This path, returned by `target_filesearch().get_lib_path()`, has - // already had `fix_windows_verbatim_for_gcc()` applied if needed. - sysroot_lib_path + // This path already had `fix_windows_verbatim_for_gcc()` applied if needed. + sysroot_lib_path.clone() } else { fix_windows_verbatim_for_gcc(lib_dir) } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 70b45a852ca..7ad31802454 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -754,7 +754,7 @@ pub(crate) enum WorkItem<B: WriteBackendMethods> { } impl<B: WriteBackendMethods> WorkItem<B> { - pub fn module_kind(&self) -> ModuleKind { + fn module_kind(&self) -> ModuleKind { match *self { WorkItem::Optimize(ref m) => m.kind, WorkItem::CopyPostLtoArtifacts(_) | WorkItem::LTO(_) => ModuleKind::Regular, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4ab20c154cc..209750d6ba6 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,5 +1,6 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; use rustc_hir as hir; @@ -8,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{lang_items, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -17,6 +18,7 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; +use rustc_target::abi::VariantIdx; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; @@ -78,6 +80,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; + let fn_sig_outer = || { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } + }; + for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -85,16 +94,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { - Some(tcx.fn_sig(did)) - } else { + let sig = fn_sig_outer(); + if sig.is_none() { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); - None } + sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -613,7 +618,93 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - // If a function uses #[target_feature] it can't be inlined into general + if let Some(sig) = fn_sig_outer() { + // Collect target features from types reachable from arguments. + // We define a type as "reachable" if: + // - it is a function argument + // - it is a field of a reachable struct + // - there is a reachable reference to it + // FIXME(struct_target_features): we may want to cache the result of this computation. + let mut visited_types = FxHashSet::default(); + let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); + let mut additional_tf = vec![]; + + while let Some(ty) = reachable_types.pop() { + if visited_types.contains(&ty) { + continue; + } + visited_types.insert(ty); + match ty.kind() { + ty::Alias(..) => { + if let Ok(t) = + tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) + { + reachable_types.push(t) + } + } + + ty::Ref(_, inner, _) => reachable_types.push(*inner), + ty::Tuple(tys) => reachable_types.extend(tys.iter()), + ty::Adt(adt_def, args) => { + additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); + // This only recurses into structs as i.e. an Option<TargetFeature> is an ADT + // that doesn't actually always contain a TargetFeature. + if adt_def.is_struct() { + reachable_types.extend( + adt_def + .variant(VariantIdx::from_usize(0)) + .fields + .iter() + .map(|field| field.ty(tcx, args)), + ); + } + } + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Foreign(..) + | ty::Str + | ty::Array(..) + | ty::Pat(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) + | ty::Error(..) => (), + } + } + + // FIXME(struct_target_features): is this really necessary? + if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a function with non-Rust ABI", + ); + } + if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a #[inline(always)] function", + ); + } + codegen_fn_attrs + .target_features + .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); + } + + // If a function uses non-default target_features it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. @@ -758,6 +849,20 @@ fn check_link_name_xor_ordinal( } } +fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { + let mut features = vec![]; + let supported_features = tcx.supported_target_features(LOCAL_CRATE); + for attr in tcx.get_attrs(def_id, sym::target_feature) { + from_target_feature(tcx, attr, supported_features, &mut features); + } + tcx.arena.alloc_slice(&features) +} + pub fn provide(providers: &mut Providers) { - *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; + *providers = Providers { + codegen_fn_attrs, + should_inherit_track_caller, + struct_target_features, + ..*providers + }; } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index cb6d9d6f66e..c89bfca6687 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -12,6 +12,7 @@ #![feature(rustdoc_internals)] #![feature(strict_provenance)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end //! This crate contains codegen code that is used by all codegen backends (LLVM and others). diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index c8cf341628c..386e1f91e7f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -13,7 +13,7 @@ use tracing::debug; use super::FunctionCx; use crate::traits::*; -pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, ) -> BitSet<mir::Local> { let mir = fx.mir; @@ -251,14 +251,14 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum CleanupKind { +pub(crate) enum CleanupKind { NotCleanup, Funclet, Internal { funclet: mir::BasicBlock }, } impl CleanupKind { - pub fn funclet_bb(self, for_bb: mir::BasicBlock) -> Option<mir::BasicBlock> { + pub(crate) fn funclet_bb(self, for_bb: mir::BasicBlock) -> Option<mir::BasicBlock> { match self { CleanupKind::NotCleanup => None, CleanupKind::Funclet => Some(for_bb), @@ -270,7 +270,7 @@ impl CleanupKind { /// MSVC requires unwinding code to be split to a tree of *funclets*, where each funclet can only /// branch to itself or to its parent. Luckily, the code we generates matches this pattern. /// Recover that structure in an analyze pass. -pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> { +pub(crate) fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> { fn discover_masters<'tcx>( result: &mut IndexSlice<mir::BasicBlock, CleanupKind>, mir: &mir::Body<'tcx>, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 1442f1832b9..db788b6b151 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -402,9 +402,6 @@ const_eval_unallowed_mutable_refs = const_eval_unallowed_op_in_const_context = {$msg} -const_eval_unavailable_target_features_for_fn = - calling a function that requires unavailable target features: {$unavailable_feats} - const_eval_uninhabited_enum_variant_read = read discriminant of an uninhabited enum variant const_eval_uninhabited_enum_variant_written = @@ -419,7 +416,7 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unstable_in_stable = const-stable function cannot use `#[feature({$gate})]` .unstable_sugg = if it is not part of the public API, make this function unstably const - .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) const_eval_unterminated_c_string = reading a null-terminated string starting at {$pointer} with no null found before end of allocation diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 86a5afa65ba..6a086a3a7e5 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -1,6 +1,7 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. use std::assert_matches::assert_matches; +use std::borrow::Cow; use std::mem; use std::ops::Deref; @@ -15,6 +16,8 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_mir_dataflow::impls::MaybeStorageLive; +use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::Analysis; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -188,8 +191,9 @@ pub struct Checker<'mir, 'tcx> { /// The span of the current statement. span: Span, - /// A set that stores for each local whether it has a `StorageDead` for it somewhere. - local_has_storage_dead: Option<BitSet<Local>>, + /// A set that stores for each local whether it is "transient", i.e. guaranteed to be dead + /// when this MIR body returns. + transient_locals: Option<BitSet<Local>>, error_emitted: Option<ErrorGuaranteed>, secondary_errors: Vec<Diag<'tcx>>, @@ -209,7 +213,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { span: ccx.body.span, ccx, qualifs: Default::default(), - local_has_storage_dead: None, + transient_locals: None, error_emitted: None, secondary_errors: Vec::new(), } @@ -264,23 +268,33 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { } } - fn local_has_storage_dead(&mut self, local: Local) -> bool { + fn local_is_transient(&mut self, local: Local) -> bool { let ccx = self.ccx; - self.local_has_storage_dead + self.transient_locals .get_or_insert_with(|| { - struct StorageDeads { - locals: BitSet<Local>, - } - impl<'tcx> Visitor<'tcx> for StorageDeads { - fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) { - if let StatementKind::StorageDead(l) = stmt.kind { - self.locals.insert(l); - } + // A local is "transient" if it is guaranteed dead at all `Return`. + // So first compute the say of "maybe live" locals at each program point. + let always_live_locals = &always_storage_live_locals(&ccx.body); + let mut maybe_storage_live = + MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) + .into_engine(ccx.tcx, &ccx.body) + .iterate_to_fixpoint() + .into_results_cursor(&ccx.body); + + // And then check all `Return` in the MIR, and if a local is "maybe live" at a + // `Return` then it is definitely not transient. + let mut transient = BitSet::new_filled(ccx.body.local_decls.len()); + // Make sure to only visit reachable blocks, the dataflow engine can ICE otherwise. + for (bb, data) in traversal::reachable(&ccx.body) { + if matches!(data.terminator().kind, TerminatorKind::Return) { + let location = ccx.body.terminator_loc(bb); + maybe_storage_live.seek_after_primary_effect(location); + // If a local may be live here, it is definitely not transient. + transient.subtract(maybe_storage_live.get()); } } - let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) }; - v.visit_body(ccx.body); - v.locals + + transient }) .contains(local) } @@ -375,7 +389,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { // `StorageDead` in every control flow path leading to a `return` terminator. // The good news is that interning will detect if any unexpected mutable // pointer slips through. - if place.is_indirect() || self.local_has_storage_dead(place.local) { + if place.is_indirect() || self.local_is_transient(place.local) { self.check_op(ops::TransientMutBorrow(kind)); } else { self.check_op(ops::MutBorrow(kind)); @@ -526,7 +540,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // `StorageDead` in every control flow path leading to a `return` terminator. // The good news is that interning will detect if any unexpected mutable // pointer slips through. - if self.local_has_storage_dead(place.local) { + if self.local_is_transient(place.local) { self.check_op(ops::TransientCellBorrow); } else { self.check_op(ops::CellBorrow); @@ -575,10 +589,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(self.body, self.tcx); - if is_int_bool_or_char(ty) { - // Int, bool, and char operations are fine. - } else if ty.is_floating_point() { - self.check_op(ops::FloatingPointOp); + if is_int_bool_float_or_char(ty) { + // Int, bool, float, and char operations are fine. } else { span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty); } @@ -588,8 +600,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let lhs_ty = lhs.ty(self.body, self.tcx); let rhs_ty = rhs.ty(self.body, self.tcx); - if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) { - // Int, bool, and char operations are fine. + if is_int_bool_float_or_char(lhs_ty) && is_int_bool_float_or_char(rhs_ty) { + // Int, bool, float, and char operations are fine. } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() { assert_matches!( op, @@ -603,8 +615,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); self.check_op(ops::RawPtrComparison); - } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() { - self.check_op(ops::FloatingPointOp); } else { span_bug!( self.span, @@ -1009,8 +1019,8 @@ fn place_as_reborrow<'tcx>( } } -fn is_int_bool_or_char(ty: Ty<'_>) -> bool { - ty.is_bool() || ty.is_integral() || ty.is_char() +fn is_int_bool_float_or_char(ty: Ty<'_>) -> bool { + ty.is_bool() || ty.is_integral() || ty.is_char() || ty.is_floating_point() } fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) { diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 259114dbdc2..93fafa60557 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -55,28 +55,6 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx>; } -#[derive(Debug)] -pub struct FloatingPointOp; -impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { - fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status { - if ccx.const_kind() == hir::ConstContext::ConstFn { - Status::Unstable(sym::const_fn_floating_point_arithmetic) - } else { - Status::Allowed - } - } - - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - feature_err( - &ccx.tcx.sess, - sym::const_fn_floating_point_arithmetic, - span, - format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()), - ) - } -} - /// A function call where the callee is a pointer. #[derive(Debug)] pub struct FnCallIndirect; @@ -440,22 +418,12 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { DiagImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - // FIXME: Maybe a more elegant solution to this if else case - if let hir::ConstContext::Static(_) = ccx.const_kind() { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { - span, - opt_help: true, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0492), - }) - } else { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { - span, - opt_help: false, - kind: ccx.const_kind(), - teach: ccx.tcx.sess.teach(E0492), - }) - } + ccx.dcx().create_err(errors::InteriorMutableDataRefer { + span, + opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)), + kind: ccx.const_kind(), + teach: ccx.tcx.sess.teach(E0492), + }) } } diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index c4f06e5af0b..f0998300dc8 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -9,13 +9,19 @@ use super::check::Qualifs; use super::ops::{self, NonConstOp}; use super::qualifs::{NeedsNonConstDrop, Qualif}; use super::ConstCx; +use crate::check_consts::rustc_allow_const_fn_unstable; /// Returns `true` if we should use the more precise live drop checker that runs after drop /// elaboration. pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { - // Const-stable functions must always use the stable live drop checker. + // Const-stable functions must always use the stable live drop checker... if ccx.is_const_stable_const_fn() { - return false; + // ...except if they have the feature flag set via `rustc_allow_const_fn_unstable`. + return rustc_allow_const_fn_unstable( + ccx.tcx, + ccx.body.source.def_id().expect_local(), + sym::const_precise_live_drops, + ); } ccx.tcx.features().const_precise_live_drops diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 00bbd9337f7..25b32785b7d 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -22,6 +22,7 @@ pub enum ConstEvalErrKind { RecursiveStatic, AssertFailure(AssertKind<ConstInt>), Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, + WriteThroughImmutablePointer, } impl MachineStopType for ConstEvalErrKind { @@ -35,12 +36,16 @@ impl MachineStopType for ConstEvalErrKind { Panic { .. } => const_eval_panic, RecursiveStatic => const_eval_recursive_static, AssertFailure(x) => x.diagnostic_message(), + WriteThroughImmutablePointer => const_eval_write_through_immutable_pointer, } } fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) { use ConstEvalErrKind::*; match *self { - RecursiveStatic | ConstAccessesMutGlobal | ModifiedGlobal => {} + RecursiveStatic + | ConstAccessesMutGlobal + | ModifiedGlobal + | WriteThroughImmutablePointer => {} AssertFailure(kind) => kind.add_args(adder), Panic { msg, line, col, file } => { adder("msg".into(), msg.into_diag_arg()); @@ -159,6 +164,7 @@ where /// Emit a lint from a const-eval situation, with a backtrace. // Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future! +#[allow(unused)] pub(super) fn lint<'tcx, L>( tcx: TyCtxtAt<'tcx>, machine: &CompileTimeMachine<'tcx>, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c3d94ca0e59..9c1fef095f5 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -12,7 +12,6 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::abi::{Align, Size}; @@ -732,8 +731,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } fn before_memory_write( - tcx: TyCtxtAt<'tcx>, - machine: &mut Self, + _tcx: TyCtxtAt<'tcx>, + _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, (_alloc_id, immutable): (AllocId, bool), range: AllocRange, @@ -744,9 +743,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } // Reject writes through immutable pointers. if immutable { - super::lint(tcx, machine, WRITES_THROUGH_IMMUTABLE_POINTER, |frames| { - crate::errors::WriteThroughImmutablePointer { frames } - }); + return Err(ConstEvalErrKind::WriteThroughImmutablePointer.into()); } // Everything else is fine. Ok(()) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 6075f3f84cd..0b366b43f95 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -407,13 +407,6 @@ pub struct ConstEvalError { pub frame_notes: Vec<FrameNote>, } -#[derive(LintDiagnostic)] -#[diag(const_eval_write_through_immutable_pointer)] -pub struct WriteThroughImmutablePointer { - #[subdiagnostic] - pub frames: Vec<FrameNote>, -} - #[derive(Diagnostic)] #[diag(const_eval_nullary_intrinsic_fail)] pub struct NullaryIntrinsicError { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 917a2fa7c6d..61e8007e10e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -311,34 +311,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) } - fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> { - // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988 - let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - if !self.tcx.sess.target.is_like_wasm - && attrs - .target_features - .iter() - .any(|feature| !self.tcx.sess.target_features.contains(&feature.name)) - { - throw_ub_custom!( - fluent::const_eval_unavailable_target_features_for_fn, - unavailable_feats = attrs - .target_features - .iter() - .filter(|&feature| !feature.implied - && !self.tcx.sess.target_features.contains(&feature.name)) - .fold(String::new(), |mut s, feature| { - if !s.is_empty() { - s.push_str(", "); - } - s.push_str(feature.name.as_str()); - s - }), - ); - } - Ok(()) - } - /// The main entry point for creating a new stack frame: performs ABI checks and initializes /// arguments. #[instrument(skip(self), level = "trace")] @@ -360,20 +332,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_unsup_format!("calling a c-variadic function is not supported"); } - if M::enforce_abi(self) { - if caller_fn_abi.conv != callee_fn_abi.conv { - throw_ub_custom!( - fluent::const_eval_incompatible_calling_conventions, - callee_conv = format!("{:?}", callee_fn_abi.conv), - caller_conv = format!("{:?}", caller_fn_abi.conv), - ) - } + if caller_fn_abi.conv != callee_fn_abi.conv { + throw_ub_custom!( + fluent::const_eval_incompatible_calling_conventions, + callee_conv = format!("{:?}", callee_fn_abi.conv), + caller_conv = format!("{:?}", caller_fn_abi.conv), + ) } // Check that all target features required by the callee (i.e., from // the attribute `#[target_feature(enable = ...)]`) are enabled at // compile time. - self.check_fn_target_features(instance)?; + M::check_fn_target_features(self, instance)?; if !callee_fn_abi.can_unwind { // The callee cannot unwind, so force the `Unreachable` unwind handling. @@ -576,7 +546,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 4901e4b2a41..e8c9f145eea 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -388,7 +388,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); - match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { + match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { let ptr = self.read_pointer(src)?; let val = Immediate::new_slice( @@ -478,9 +478,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); - match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { + match (src.layout.ty.kind(), cast_ty.ty.kind()) { (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _)) - | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, *s, *c), + | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); // implies same number of fields diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index aef39b9af2f..bedc56de0da 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -684,19 +684,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(layout.is_sized()); let get_bytes = |this: &InterpCx<'tcx, M>, - op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>, - size| + op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>| -> InterpResult<'tcx, &[u8]> { let ptr = this.read_pointer(op)?; - let Some(alloc_ref) = self.get_ptr_alloc(ptr, size)? else { + this.check_ptr_align(ptr, layout.align.abi)?; + let Some(alloc_ref) = self.get_ptr_alloc(ptr, layout.size)? else { // zero-sized access return Ok(&[]); }; alloc_ref.get_bytes_strip_provenance() }; - let lhs_bytes = get_bytes(self, lhs, layout.size)?; - let rhs_bytes = get_bytes(self, rhs, layout.size)?; + let lhs_bytes = get_bytes(self, lhs)?; + let rhs_bytes = get_bytes(self, rhs)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 761ab81e228..88453245b84 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -173,11 +173,6 @@ pub trait Machine<'tcx>: Sized { false } - /// Whether function calls should be [ABI](CallAbi)-checked. - fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool { - true - } - /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually /// check for overflow. fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool; @@ -238,6 +233,13 @@ pub trait Machine<'tcx>: Sized { unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>; + /// Check whether the given function may be executed on the current machine, in terms of the + /// target features is requires. + fn check_fn_target_features( + _ecx: &InterpCx<'tcx, Self>, + _instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx>; + /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'tcx, Self>, @@ -280,6 +282,9 @@ pub trait Machine<'tcx>: Sized { Ok(()) } + /// Determines the result of a `NullaryOp::UbChecks` invocation. + fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>; + /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. #[inline] @@ -615,6 +620,16 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] + fn check_fn_target_features( + _ecx: &InterpCx<$tcx, Self>, + _instance: ty::Instance<$tcx>, + ) -> InterpResult<$tcx> { + // For now we don't do any checking here. We can't use `tcx.sess` because that can differ + // between crates, and we need to ensure that const-eval always behaves the same. + Ok(()) + } + + #[inline(always)] fn call_extra_fn( _ecx: &mut InterpCx<$tcx, Self>, fn_val: !, @@ -628,6 +643,13 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] + fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> { + // We can't look at `tcx.sess` here as that can differ across crates, which can lead to + // unsound differences in evaluating the same constant at different instantiation sites. + Ok(true) + } + + #[inline(always)] fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, _id: AllocId, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 910aec9b8e1..97326fe99a2 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1014,7 +1014,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// We do this so Miri's allocation access tracking does not show the validation /// reads as spurious accesses. - pub(super) fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R { + pub fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. assert!( diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ad87d6953d3..9a8ccaa7cc5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -319,6 +319,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { // some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try // to detect those here and also give them no data _ if matches!(layout.abi, Abi::Aggregate { .. }) + && matches!(layout.variants, abi::Variants::Single { .. }) && matches!(&layout.fields, abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0) => { Immediate::Uninit @@ -328,8 +329,9 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { assert_eq!(offset.bytes(), 0); assert!( match (self.layout.abi, layout.abi) { - (Abi::Scalar(..), Abi::Scalar(..)) => true, - (Abi::ScalarPair(..), Abi::ScalarPair(..)) => true, + (Abi::Scalar(l), Abi::Scalar(r)) => l.size(cx) == r.size(cx), + (Abi::ScalarPair(l1, l2), Abi::ScalarPair(r1, r2)) => + l1.size(cx) == r1.size(cx) && l2.size(cx) == r2.size(cx), _ => false, }, "cannot project into {} immediate with equally-sized field {}\nouter ABI: {:#?}\nfield ABI: {:#?}", @@ -344,16 +346,23 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { assert_matches!(layout.abi, Abi::Scalar(..)); Immediate::from(if offset.bytes() == 0 { - debug_assert_eq!(layout.size, a.size(cx)); + // It is "okay" to transmute from `usize` to a pointer (GVN relies on that). + // So only compare the size. + assert_eq!(layout.size, a.size(cx)); a_val } else { - debug_assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); - debug_assert_eq!(layout.size, b.size(cx)); + assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); + assert_eq!(layout.size, b.size(cx)); b_val }) } // everything else is a bug - _ => bug!("invalid field access on immediate {}, layout {:#?}", self, self.layout), + _ => bug!( + "invalid field access on immediate {} at offset {}, original layout {:#?}", + self, + offset.bytes(), + self.layout + ), }; ImmTy::from_immediate(inner_val, layout) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 2f860f9f942..e9ba12dbcc4 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -512,7 +512,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } - UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx), + UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), }) } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2b7dc040f64..e49ae60e890 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -7,6 +7,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable +#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(decl_macro)] @@ -15,6 +16,7 @@ #![feature(panic_update_hook)] #![feature(result_flattening)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cmp::max; @@ -391,13 +393,17 @@ fn run_compiler( let linker = compiler.enter(|queries| { let early_exit = || early_exit().map(|_| None); + + // Parse the crate root source code (doesn't parse submodules yet) + // Everything else is parsed during macro expansion. queries.parse()?; - if let Some(ppm) = &sess.opts.pretty { - if ppm.needs_ast_map() { + // If pretty printing is requested: Figure out the representation, print it and exit + if let Some(pp_mode) = sess.opts.pretty { + if pp_mode.needs_ast_map() { queries.global_ctxt()?.enter(|tcx| { tcx.ensure().early_lint_checks(()); - pretty::print(sess, *ppm, pretty::PrintExtra::NeedsAstMap { tcx }); + pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx }); Ok(()) })?; @@ -408,7 +414,7 @@ fn run_compiler( let krate = queries.parse()?; pretty::print( sess, - *ppm, + pp_mode, pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() }, ); } @@ -463,12 +469,8 @@ fn run_compiler( linker.link(sess, codegen_backend)? } - if sess.opts.unstable_opts.print_fuel.is_some() { - eprintln!( - "Fuel used by {}: {}", - sess.opts.unstable_opts.print_fuel.as_ref().unwrap(), - sess.print_fuel.load(Ordering::SeqCst) - ); + if let Some(fuel) = sess.opts.unstable_opts.print_fuel.as_deref() { + eprintln!("Fuel used by {}: {}", fuel, sess.print_fuel.load(Ordering::SeqCst)); } Ok(()) @@ -485,36 +487,43 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileNa (odir, ofile) } -// Extract input (string or file and optional path) from matches. +/// Extract input (string or file and optional path) from matches. +/// This handles reading from stdin if `-` is provided. fn make_input( early_dcx: &EarlyDiagCtxt, free_matches: &[String], ) -> Result<Option<Input>, ErrorGuaranteed> { - let [ifile] = free_matches else { return Ok(None) }; - if ifile == "-" { - let mut src = String::new(); - if io::stdin().read_to_string(&mut src).is_err() { - // Immediately stop compilation if there was an issue reading - // the input (for example if the input stream is not UTF-8). - let reported = - early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); - return Err(reported); - } - if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + let [input_file] = free_matches else { return Ok(None) }; + + if input_file != "-" { + // Normal `Input::File` + return Ok(Some(Input::File(PathBuf::from(input_file)))); + } + + // read from stdin as `Input::Str` + let mut input = String::new(); + if io::stdin().read_to_string(&mut input).is_err() { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + let reported = + early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); + return Err(reported); + } + + let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + Ok(path) => { let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect( "when UNSTABLE_RUSTDOC_TEST_PATH is set \ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set", ); let line = isize::from_str_radix(&line, 10) .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number"); - let file_name = FileName::doc_test_source_code(PathBuf::from(path), line); - Ok(Some(Input::Str { name: file_name, input: src })) - } else { - Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src })) + FileName::doc_test_source_code(PathBuf::from(path), line) } - } else { - Ok(Some(Input::File(PathBuf::from(ifile)))) - } + Err(_) => FileName::anon_source_code(&input), + }; + + Ok(Some(Input::Str { name, input })) } /// Whether to stop or continue compilation. diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs index 51f2a508cf9..e1f868c2522 100644 --- a/compiler/rustc_driver_impl/src/signal_handler.rs +++ b/compiler/rustc_driver_impl/src/signal_handler.rs @@ -6,7 +6,7 @@ use std::{fmt, mem, ptr}; use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE}; -extern "C" { +unsafe extern "C" { fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int); } diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 2a7bc2501c0..150f99a3ee7 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -6,6 +6,7 @@ #![deny(rustdoc::invalid_codeblock_attributes)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // This higher-order macro defines the error codes that are in use. It is used diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 87dee2898da..e84d7be45d7 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -4,6 +4,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(type_alias_impl_trait)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index fae8b5647fc..3303e4ee752 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -204,7 +204,7 @@ pub trait LintDiagnostic<'a, G: EmissionGuarantee> { } #[derive(Clone, Debug, Encodable, Decodable)] -pub struct DiagLocation { +pub(crate) struct DiagLocation { file: Cow<'static, str>, line: u32, col: u32, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 9ce5d77ef6c..2bc29dabd18 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2387,7 +2387,7 @@ enum DisplaySuggestion { impl FileWithAnnotatedLines { /// Preprocess all the annotations so that they are grouped by file and by line number /// This helps us quickly iterate over the whole message (including secondary file spans) - pub fn collect_annotations( + pub(crate) fn collect_annotations( emitter: &dyn Emitter, args: &FluentArgs<'_>, msp: &MultiSpan, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fd203c38318..99ee8fb17d7 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -25,6 +25,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_errors; @@ -1701,7 +1702,7 @@ impl DiagCtxtInner { } /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. - pub fn eagerly_translate<'a>( + fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator<Item = DiagArg<'a>>, @@ -1710,7 +1711,7 @@ impl DiagCtxtInner { } /// Translate `message` eagerly with `args` to `String`. - pub fn eagerly_translate_to_string<'a>( + fn eagerly_translate_to_string<'a>( &self, message: DiagMessage, args: impl Iterator<Item = DiagArg<'a>>, diff --git a/compiler/rustc_errors/src/lock.rs b/compiler/rustc_errors/src/lock.rs index 915542c9092..7557969f374 100644 --- a/compiler/rustc_errors/src/lock.rs +++ b/compiler/rustc_errors/src/lock.rs @@ -12,7 +12,7 @@ use std::any::Any; #[cfg(windows)] -pub fn acquire_global_lock(name: &str) -> Box<dyn Any> { +pub(crate) fn acquire_global_lock(name: &str) -> Box<dyn Any> { use std::ffi::CString; use std::io; @@ -80,6 +80,6 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> { } #[cfg(not(windows))] -pub fn acquire_global_lock(_name: &str) -> Box<dyn Any> { +pub(crate) fn acquire_global_lock(_name: &str) -> Box<dyn Any> { Box::new(()) } diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index c44f136120a..b1db44dd215 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -74,13 +74,13 @@ enum ParseOpt { } /// Parse a buffer -pub fn entrypoint(txt: &str) -> MdStream<'_> { +pub(crate) fn entrypoint(txt: &str) -> MdStream<'_> { let ctx = Context { top_block: true, prev: Prev::Newline }; normalize(parse_recursive(txt.trim().as_bytes(), ctx), &mut Vec::new()) } /// Parse a buffer with specified context -fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> { +fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'a> { use ParseOpt as Po; use Prev::{Escape, Newline, Whitespace}; diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index 06c1333d93d..579e00b8b85 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -15,7 +15,7 @@ thread_local! { } /// Print to terminal output to a buffer -pub fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { +pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { #[cfg(not(test))] if let Some((w, _)) = termize::dimensions() { WIDTH.with(|c| c.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH))); @@ -47,7 +47,7 @@ fn write_stream( Ok(()) } -pub fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> { +fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> { match tt { MdTree::CodeBlock { txt, lang: _ } => { buf.set_color(ColorSpec::new().set_dimmed(true))?; diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 50abf8a49c2..8485d7087cf 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -5,13 +5,13 @@ use rustc_macros::{Decodable, Encodable}; use crate::{Level, Loc}; #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Line { +pub(crate) struct Line { pub line_index: usize, pub annotations: Vec<Annotation>, } #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Default)] -pub struct AnnotationColumn { +pub(crate) struct AnnotationColumn { /// the (0-indexed) column for *display* purposes, counted in characters, not utf-8 bytes pub display: usize, /// the (0-indexed) column in the file, counted in characters, not utf-8 bytes. @@ -31,13 +31,13 @@ pub struct AnnotationColumn { } impl AnnotationColumn { - pub fn from_loc(loc: &Loc) -> AnnotationColumn { + pub(crate) fn from_loc(loc: &Loc) -> AnnotationColumn { AnnotationColumn { display: loc.col_display, file: loc.col.0 } } } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct MultilineAnnotation { +pub(crate) struct MultilineAnnotation { pub depth: usize, pub line_start: usize, pub line_end: usize, @@ -49,19 +49,19 @@ pub struct MultilineAnnotation { } impl MultilineAnnotation { - pub fn increase_depth(&mut self) { + pub(crate) fn increase_depth(&mut self) { self.depth += 1; } /// Compare two `MultilineAnnotation`s considering only the `Span` they cover. - pub fn same_span(&self, other: &MultilineAnnotation) -> bool { + pub(crate) fn same_span(&self, other: &MultilineAnnotation) -> bool { self.line_start == other.line_start && self.line_end == other.line_end && self.start_col == other.start_col && self.end_col == other.end_col } - pub fn as_start(&self) -> Annotation { + pub(crate) fn as_start(&self) -> Annotation { Annotation { start_col: self.start_col, end_col: AnnotationColumn { @@ -76,7 +76,7 @@ impl MultilineAnnotation { } } - pub fn as_end(&self) -> Annotation { + pub(crate) fn as_end(&self) -> Annotation { Annotation { start_col: AnnotationColumn { // these might not correspond to the same place anymore, @@ -91,7 +91,7 @@ impl MultilineAnnotation { } } - pub fn as_line(&self) -> Annotation { + pub(crate) fn as_line(&self) -> Annotation { Annotation { start_col: Default::default(), end_col: Default::default(), @@ -103,7 +103,7 @@ impl MultilineAnnotation { } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub enum AnnotationType { +pub(crate) enum AnnotationType { /// Annotation under a single line of code Singleline, @@ -129,7 +129,7 @@ pub enum AnnotationType { } #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Annotation { +pub(crate) struct Annotation { /// Start column. /// Note that it is important that this field goes /// first, so that when we sort, we sort orderings by start @@ -152,12 +152,12 @@ pub struct Annotation { impl Annotation { /// Whether this annotation is a vertical line placeholder. - pub fn is_line(&self) -> bool { + pub(crate) fn is_line(&self) -> bool { matches!(self.annotation_type, AnnotationType::MultilineLine(_)) } /// Length of this annotation as displayed in the stderr output - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { // Account for usize underflows if self.end_col.display > self.start_col.display { self.end_col.display - self.start_col.display @@ -166,7 +166,7 @@ impl Annotation { } } - pub fn has_label(&self) -> bool { + pub(crate) fn has_label(&self) -> bool { if let Some(ref label) = self.label { // Consider labels with no text as effectively not being there // to avoid weird output with unnecessary vertical lines, like: @@ -184,7 +184,7 @@ impl Annotation { } } - pub fn takes_space(&self) -> bool { + pub(crate) fn takes_space(&self) -> bool { // Multiline annotations always have to keep vertical space. matches!( self.annotation_type, @@ -194,7 +194,7 @@ impl Annotation { } #[derive(Debug)] -pub struct StyledString { +pub(crate) struct StyledString { pub text: String, pub style: Style, } diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs index 9aa14e1f214..5ca9e9b18f3 100644 --- a/compiler/rustc_errors/src/styled_buffer.rs +++ b/compiler/rustc_errors/src/styled_buffer.rs @@ -3,7 +3,7 @@ use crate::snippet::{Style, StyledString}; #[derive(Debug)] -pub struct StyledBuffer { +pub(crate) struct StyledBuffer { lines: Vec<Vec<StyledChar>>, } @@ -22,12 +22,12 @@ impl StyledChar { } impl StyledBuffer { - pub fn new() -> StyledBuffer { + pub(crate) fn new() -> StyledBuffer { StyledBuffer { lines: vec![] } } /// Returns content of `StyledBuffer` split by lines and line styles - pub fn render(&self) -> Vec<Vec<StyledString>> { + pub(crate) fn render(&self) -> Vec<Vec<StyledString>> { // Tabs are assumed to have been replaced by spaces in calling code. debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t'))); @@ -70,7 +70,7 @@ impl StyledBuffer { /// Sets `chr` with `style` for given `line`, `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. - pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { + pub(crate) fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) { self.ensure_lines(line); if col >= self.lines[line].len() { self.lines[line].resize(col + 1, StyledChar::SPACE); @@ -81,7 +81,7 @@ impl StyledBuffer { /// Sets `string` with `style` for given `line`, starting from `col`. /// If `line` does not exist in our buffer, adds empty lines up to the given /// and fills the last line with unstyled whitespace. - pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { + pub(crate) fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { let mut n = col; for c in string.chars() { self.putc(line, n, c, style); @@ -91,7 +91,7 @@ impl StyledBuffer { /// For given `line` inserts `string` with `style` before old content of that line, /// adding lines if needed - pub fn prepend(&mut self, line: usize, string: &str, style: Style) { + pub(crate) fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); let string_len = string.chars().count(); @@ -107,7 +107,7 @@ impl StyledBuffer { /// For given `line` inserts `string` with `style` after old content of that line, /// adding lines if needed - pub fn append(&mut self, line: usize, string: &str, style: Style) { + pub(crate) fn append(&mut self, line: usize, string: &str, style: Style) { if line >= self.lines.len() { self.puts(line, 0, string, style); } else { @@ -116,14 +116,14 @@ impl StyledBuffer { } } - pub fn num_lines(&self) -> usize { + pub(crate) fn num_lines(&self) -> usize { self.lines.len() } /// Set `style` for `line`, `col_start..col_end` range if: /// 1. That line and column range exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` - pub fn set_style_range( + pub(crate) fn set_style_range( &mut self, line: usize, col_start: usize, @@ -139,7 +139,7 @@ impl StyledBuffer { /// Set `style` for `line`, `col` if: /// 1. That line and column exist in `StyledBuffer` /// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation` - pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { + fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) { if let Some(ref mut line) = self.lines.get_mut(line) { if let Some(StyledChar { style: s, .. }) = line.get_mut(col) { if overwrite || matches!(s, Style::NoStyle | Style::Quotation) { diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index a44e794ee12..e0b64b276eb 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -59,7 +59,7 @@ pub trait Translate { &'a self, message: &'a DiagMessage, args: &'a FluentArgs<'_>, - ) -> Result<Cow<'_, str>, TranslateError<'_>> { + ) -> Result<Cow<'a, str>, TranslateError<'a>> { trace!(?message, ?args); let (identifier, attr) = match message { DiagMessage::Str(msg) | DiagMessage::Translated(msg) => { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index f6b5cd394b6..0fdccb08918 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -350,7 +350,7 @@ pub(crate) struct ModuleMultipleCandidates { #[derive(Diagnostic)] #[diag(expand_trace_macro)] -pub struct TraceMacro { +pub(crate) struct TraceMacro { #[primary_span] pub span: Span, } @@ -402,14 +402,14 @@ pub(crate) struct CustomAttributePanickedHelp { #[derive(Diagnostic)] #[diag(expand_proc_macro_derive_tokens)] -pub struct ProcMacroDeriveTokens { +pub(crate) struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(expand_duplicate_matcher_binding)] -pub struct DuplicateMatcherBinding { +pub(crate) struct DuplicateMatcherBinding { #[primary_span] #[label] pub span: Span, @@ -421,7 +421,7 @@ pub struct DuplicateMatcherBinding { #[diag(expand_missing_fragment_specifier)] #[note] #[help(expand_valid)] -pub struct MissingFragmentSpecifier { +pub(crate) struct MissingFragmentSpecifier { #[primary_span] pub span: Span, #[suggestion( @@ -437,7 +437,7 @@ pub struct MissingFragmentSpecifier { #[derive(Diagnostic)] #[diag(expand_invalid_fragment_specifier)] #[help] -pub struct InvalidFragmentSpecifier { +pub(crate) struct InvalidFragmentSpecifier { #[primary_span] pub span: Span, pub fragment: Ident, @@ -446,7 +446,7 @@ pub struct InvalidFragmentSpecifier { #[derive(Diagnostic)] #[diag(expand_expected_paren_or_brace)] -pub struct ExpectedParenOrBrace<'a> { +pub(crate) struct ExpectedParenOrBrace<'a> { #[primary_span] pub span: Span, pub token: Cow<'a, str>, @@ -479,7 +479,7 @@ pub(crate) struct GlobDelegationTraitlessQpath { #[derive(Diagnostic)] #[diag(expand_proc_macro_back_compat)] #[note] -pub struct ProcMacroBackCompat { +pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 4222c9fe906..777044e3f33 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -13,6 +13,7 @@ #![feature(rustdoc_internals)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro as pm; diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 628c6bfeb79..5778f661622 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -196,13 +196,14 @@ impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> { } } -/// Currently used by macro_rules! compilation to extract a little information from the `Failure` case. -pub struct FailureForwarder<'matcher> { +/// Currently used by macro_rules! compilation to extract a little information from the `Failure` +/// case. +pub(crate) struct FailureForwarder<'matcher> { expected_token: Option<&'matcher Token>, } impl<'matcher> FailureForwarder<'matcher> { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { expected_token: None } } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index e5b9c627429..9011d02da33 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -407,7 +407,7 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool { // Note: the vectors could be created and dropped within `parse_tt`, but to avoid excess // allocations we have a single vector for each kind that is cleared and reused repeatedly. -pub struct TtParser { +pub(crate) struct TtParser { macro_name: Ident, /// The set of current mps to be processed. This should be empty by the end of a successful diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index b2f7c8f5183..5df0aebfe57 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -14,12 +14,11 @@ use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ - `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ - `literal`, `path`, `meta`, `tt`, `item` and `vis`"; -pub const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ - `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \ - `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ - `item` and `vis`"; + `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ + `item` and `vis`"; +pub(crate) const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ + `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, \ + `meta`, `tt`, `item` and `vis`"; /// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 1e455d465e4..469bed3cd59 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -191,12 +191,12 @@ pub(crate) fn placeholder( } #[derive(Default)] -pub struct PlaceholderExpander { +pub(crate) struct PlaceholderExpander { expanded_fragments: FxHashMap<ast::NodeId, AstFragment>, } impl PlaceholderExpander { - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { + pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 1438d1ad11f..4ff5da1a4bd 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -414,7 +414,7 @@ impl ToInternal<rustc_errors::Level> for Level { } } -pub struct FreeFunctions; +pub(crate) struct FreeFunctions; pub(crate) struct Rustc<'a, 'b> { ecx: &'a mut ExtCtxt<'b>, @@ -426,7 +426,7 @@ pub(crate) struct Rustc<'a, 'b> { } impl<'a, 'b> Rustc<'a, 'b> { - pub fn new(ecx: &'a mut ExtCtxt<'b>) -> Self { + pub(crate) fn new(ecx: &'a mut ExtCtxt<'b>) -> Self { let expn_data = ecx.current_expansion.id.expn_data(); Rustc { def_site: ecx.with_def_site_ctxt(expn_data.def_site), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index a4a2028e26e..9223c3c322a 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -115,6 +115,8 @@ declare_features! ( (accepted, conservative_impl_trait, "1.26.0", Some(34511)), /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), + /// Allows basic arithmetic on floating point types in a `const fn`. + (accepted, const_fn_floating_point_arithmetic, "CURRENT_RUSTC_VERSION", Some(57241)), /// Allows using and casting function pointers in a `const fn`. (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)), /// Allows trait bounds in `const fn`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d4c54b67f24..2747a14d60a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -641,6 +641,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ErrorFollowing, EncodeCrossCrate::Yes, "rustc_deprecated_safe_2024 is supposed to be used in libstd only", ), + rustc_attr!( + rustc_pub_transparent, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::Yes, + "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", + ), // ========================================================================== diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index dcc1c3202ea..adaaba3cd23 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,6 +15,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod accepted; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a1741ac33ca..f7ddc3e2c56 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -193,6 +193,8 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), + /// Gating for a new desugaring of const arguments of usages of const parameters + (internal, const_arg_path, "1.81.0", None), /// Allows writing custom MIR (internal, custom_mir, "1.65.0", None), /// Outputs useful `assert!` messages @@ -300,6 +302,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. + (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), @@ -400,8 +403,6 @@ declare_features! ( (incomplete, const_closures, "1.68.0", Some(106003)), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (unstable, const_extern_fn, "1.40.0", Some(64926)), - /// Allows basic arithmetic on floating point types in a `const fn`. - (unstable, const_fn_floating_point_arithmetic, "1.48.0", Some(57241)), /// Allows `for _ in _` loops in const contexts. (unstable, const_for, "1.56.0", Some(87575)), /// Allows using `&mut` in constant functions. @@ -594,6 +595,8 @@ declare_features! ( (unstable, strict_provenance, "1.61.0", Some(95228)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows structs to carry target_feature information. + (incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)), /// Allows the use of `#[target_feature]` on safe functions. (unstable, target_feature_11, "1.45.0", Some(69098)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index 0a04e6743a8..6e5add24bcc 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -6,6 +6,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index c8f8fd5be02..b5774f64b66 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -277,6 +277,7 @@ )] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::borrow::Cow; diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 59204d79928..36e29d2dcb2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -133,6 +133,9 @@ pub enum DefKind { /// we treat them all the same, and code which needs to distinguish them can match /// or `hir::ClosureKind` or `type_of`. Closure, + /// The definition of a synthetic coroutine body created by the lowering of a + /// coroutine-closure, such as an async closure. + SyntheticCoroutineBody, } impl DefKind { @@ -177,6 +180,7 @@ impl DefKind { DefKind::Closure => "closure", DefKind::ExternCrate => "extern crate", DefKind::GlobalAsm => "global assembly block", + DefKind::SyntheticCoroutineBody => "synthetic mir body", } } @@ -236,7 +240,8 @@ impl DefKind { | DefKind::ForeignMod | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::OpaqueTy => None, + | DefKind::OpaqueTy + | DefKind::SyntheticCoroutineBody => None, } } @@ -276,6 +281,7 @@ impl DefKind { DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, DefKind::Closure => DefPathData::Closure, + DefKind::SyntheticCoroutineBody => DefPathData::Closure, } } @@ -291,7 +297,8 @@ impl DefKind { | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - | DefKind::Static { .. } => true, + | DefKind::Static { .. } + | DefKind::SyntheticCoroutineBody => true, DefKind::Mod | DefKind::Struct | DefKind::Union @@ -319,6 +326,41 @@ impl DefKind { | DefKind::ExternCrate => false, } } + + /// Whether `query struct_target_features` should be used with this definition. + pub fn has_struct_target_features(self) -> bool { + match self { + DefKind::Struct | DefKind::Union | DefKind::Enum => true, + DefKind::Fn + | DefKind::AssocFn + | DefKind::Ctor(..) + | DefKind::Closure + | DefKind::Static { .. } + | DefKind::Mod + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Const + | DefKind::AssocConst + | DefKind::Macro(..) + | DefKind::Use + | DefKind::ForeignMod + | DefKind::OpaqueTy + | DefKind::Impl { .. } + | DefKind::Field + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::SyntheticCoroutineBody + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } + } } /// The resolution of a path or export. diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index e517c3fd07a..c1a4a4497c7 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_hir; diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index c30a6f1eeb9..d0b0c08aa79 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -26,13 +26,13 @@ use rustc_span::Span; /// Our representation is a bit mixed here -- in some cases, we /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] -pub struct Bounds<'tcx> { +pub(crate) struct Bounds<'tcx> { clauses: Vec<(ty::Clause<'tcx>, Span)>, effects_min_tys: FxIndexMap<Ty<'tcx>, Span>, } impl<'tcx> Bounds<'tcx> { - pub fn push_region_bound( + pub(crate) fn push_region_bound( &mut self, tcx: TyCtxt<'tcx>, region: ty::PolyTypeOutlivesPredicate<'tcx>, @@ -42,7 +42,7 @@ impl<'tcx> Bounds<'tcx> { .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span)); } - pub fn push_trait_bound( + pub(crate) fn push_trait_bound( &mut self, tcx: TyCtxt<'tcx>, defining_def_id: DefId, @@ -154,7 +154,7 @@ impl<'tcx> Bounds<'tcx> { self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span)); } - pub fn push_projection_bound( + pub(crate) fn push_projection_bound( &mut self, tcx: TyCtxt<'tcx>, projection: ty::PolyProjectionPredicate<'tcx>, @@ -166,14 +166,14 @@ impl<'tcx> Bounds<'tcx> { )); } - pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { + pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. self.clauses.insert(0, (trait_ref.upcast(tcx), span)); } - pub fn clauses( + pub(crate) fn clauses( &self, // FIXME(effects): remove tcx _tcx: TyCtxt<'tcx>, @@ -181,7 +181,7 @@ impl<'tcx> Bounds<'tcx> { self.clauses.iter().cloned() } - pub fn effects_min_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ { + pub(crate) fn effects_min_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ { self.effects_min_tys.keys().copied() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 16eeb57b2b9..d414bcdb95b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -529,7 +529,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe match tcx.named_bound_var(hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => { - expected_captures.insert(def_id); + expected_captures.insert(def_id.to_def_id()); // Make sure we allow capturing these lifetimes through `Self` and // `T::Assoc` projection syntax, too. These will occur when we only @@ -538,7 +538,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe // feature -- see <https://github.com/rust-lang/rust/pull/115659>. if let DefKind::LifetimeParam = tcx.def_kind(def_id) && let Some(def_id) = tcx - .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + .map_opaque_lifetime_to_parent_lifetime(def_id) .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id())) { shadowed_captures.insert(def_id); @@ -1053,7 +1053,7 @@ fn check_impl_items_against_trait<'tcx>( } } -pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { +fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { let t = tcx.type_of(def_id).instantiate_identity(); if let ty::Adt(def, args) = t.kind() && def.is_struct() @@ -1259,7 +1259,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), ty::Adt(def, args) => { - if !def.did().is_local() { + if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent) + { let non_exhaustive = def.is_variant_list_non_exhaustive() || def .variants() diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 80daaa60324..d2b7ede6523 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -7,7 +7,8 @@ use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; use rustc_trait_selection::regions::InferCtxtRegionExt; @@ -177,6 +178,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; + if trait_bounds.references_error() || impl_bounds.references_error() { + return; + } + // For quicker lookup, use an `IndexSet` (we don't use one earlier because // it's not foldable..). // Also, We have to anonymize binders in these types because they may contain diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 19a0476e630..22d7d1fea9c 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use crate::errors; /// Check for shared or mutable references of `static mut` inside expression -pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { +pub(crate) fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { let span = expr.span; let hir_id = expr.hir_id; if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind @@ -26,7 +26,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { } /// Check for shared or mutable references of `static mut` inside statement -pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { +pub(crate) fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && let hir::ByRef::Yes(rmutbl) = ba.0 diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index bc6641c688c..48335173979 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -22,7 +22,7 @@ use rustc_span::source_map; use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut}; #[derive(Debug, Copy, Clone)] -pub struct Context { +struct Context { /// The scope that contains any new variables declared, plus its depth in /// the scope tree. var_parent: Option<(Scope, ScopeDepth)>, @@ -893,7 +893,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { /// re-use in incremental scenarios. We may sometimes need to rerun the /// type checker even when the HIR hasn't changed, and in those cases /// we can avoid reconstructing the region scope tree. -pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { +pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { let typeck_root_def_id = tcx.typeck_root_def_id(def_id); if typeck_root_def_id != def_id { return tcx.region_scope_tree(typeck_root_def_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d4b2c3f8a87..cb66179ec80 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -747,7 +747,7 @@ fn region_known_to_outlive<'tcx>( region_b: ty::Region<'tcx>, ) -> bool { test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { - infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a); + infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP, None), region_b, region_a); }) } @@ -2174,7 +2174,8 @@ fn lint_redundant_lifetimes<'tcx>( | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => return, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => return, } // The ordering of this lifetime map is a bit subtle. diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index ed23dc2a827..ca9e2e8a3cc 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -5,7 +5,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_unused_traits, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index fecd78bc38f..23f1adfe302 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -332,7 +332,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() } } -pub fn coerce_unsized_info<'tcx>( +pub(crate) fn coerce_unsized_info<'tcx>( tcx: TyCtxt<'tcx>, impl_did: LocalDefId, ) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> { diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 89acb778d6c..bd8b43e28e5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -19,7 +19,7 @@ use rustc_span::ErrorGuaranteed; use crate::errors; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls( +pub(crate) fn crate_inherent_impls( tcx: TyCtxt<'_>, (): (), ) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> { @@ -32,7 +32,7 @@ pub fn crate_inherent_impls( Ok(tcx.arena.alloc(collect.impls_map)) } -pub fn crate_incoherent_impls( +pub(crate) fn crate_incoherent_impls( tcx: TyCtxt<'_>, simp: SimplifiedType, ) -> Result<&[DefId], ErrorGuaranteed> { @@ -43,7 +43,10 @@ pub fn crate_incoherent_impls( } /// On-demand query: yields a vector of the inherent impls for a specific type. -pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> Result<&[DefId], ErrorGuaranteed> { +pub(crate) fn inherent_impls( + tcx: TyCtxt<'_>, + ty_def_id: LocalDefId, +) -> Result<&[DefId], ErrorGuaranteed> { let crate_map = tcx.crate_inherent_impls(())?; Ok(match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index cd5cc33d65a..00bbbf7130f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -11,7 +11,10 @@ use rustc_span::{ErrorGuaranteed, Symbol}; use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> { +pub(crate) fn crate_inherent_impls_overlap_check( + tcx: TyCtxt<'_>, + (): (), +) -> Result<(), ErrorGuaranteed> { let mut inherent_overlap_checker = InherentOverlapChecker { tcx }; let mut res = Ok(()); for id in tcx.hir().items() { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8e4da90ca26..3d800bb165c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -123,7 +123,7 @@ fn enforce_empty_impls_for_marker_traits( .emit()) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { use self::builtin::coerce_unsized_info; use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls}; use self::inherent_impls_overlap::crate_inherent_impls_overlap_check; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f75954c9edf..3acf2c63145 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -70,7 +70,6 @@ pub fn provide(providers: &mut Providers) { impl_super_outlives: item_bounds::impl_super_outlives, generics_of: generics_of::generics_of, predicates_of: predicates_of::predicates_of, - predicates_defined_on, explicit_predicates_of: predicates_of::explicit_predicates_of, explicit_super_predicates_of: predicates_of::explicit_super_predicates_of, explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of, @@ -392,7 +391,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { - if let RegionInferReason::BorrowedObjectLifetimeDefault = reason { + if let RegionInferReason::ObjectLifetimeDefault = reason { let e = struct_span_code_err!( self.dcx(), span, @@ -1775,34 +1774,6 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( }) } -/// Returns a list of type predicates for the definition with ID `def_id`, including inferred -/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus -/// inferred constraints concerning which regions outlive other regions. -#[instrument(level = "debug", skip(tcx))] -fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - let mut result = tcx.explicit_predicates_of(def_id); - debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result); - let inferred_outlives = tcx.inferred_outlives_of(def_id); - if !inferred_outlives.is_empty() { - debug!( - "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", - def_id, inferred_outlives, - ); - let inferred_outlives_iter = - inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span)); - if result.predicates.is_empty() { - result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); - } else { - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.into_iter().copied().chain(inferred_outlives_iter), - ); - } - } - - debug!("predicates_defined_on({:?}) = {:?}", def_id, result); - result -} - fn compute_sig_of_foreign_fn_decl<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6ac4802b195..bba8b0497be 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -18,10 +18,26 @@ use crate::delegation::inherit_predicates_for_delegation_item; use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; /// Returns a list of all type predicates (explicit and implicit) for the definition with -/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus -/// `Self: Trait` predicates for traits. +/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus +/// inferred constraints concerning which regions outlive other regions. +#[instrument(level = "debug", skip(tcx))] pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - let mut result = tcx.predicates_defined_on(def_id); + let mut result = tcx.explicit_predicates_of(def_id); + debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result); + + let inferred_outlives = tcx.inferred_outlives_of(def_id); + if !inferred_outlives.is_empty() { + debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,); + let inferred_outlives_iter = + inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span)); + if result.predicates.is_empty() { + result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); + } else { + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.into_iter().copied().chain(inferred_outlives_iter), + ); + } + } if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -51,7 +67,8 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))), ); } - debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); + + debug!("predicates_of({:?}) = {:?}", def_id, result); result } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae0c70d2326..e38492d9e64 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -13,7 +13,6 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node}; use rustc_macros::extension; @@ -22,7 +21,7 @@ use rustc_middle::middle::resolve_bound_vars::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_middle::{bug, span_bug}; -use rustc_span::def_id::DefId; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -32,7 +31,7 @@ use crate::errors; impl ResolvedArg { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { debug!("ResolvedArg::early: def_id={:?}", param.def_id); - (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) + (param.def_id, ResolvedArg::EarlyBound(param.def_id)) } fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { @@ -41,10 +40,10 @@ impl ResolvedArg { "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}", idx, param, depth, param.def_id, ); - (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id())) + (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id)) } - fn id(&self) -> Option<DefId> { + fn id(&self) -> Option<LocalDefId> { match *self { ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None, @@ -288,13 +287,14 @@ fn late_arg_as_bound_arg<'tcx>( ) -> ty::BoundVariableKind { match arg { ResolvedArg::LateBound(_, _, def_id) => { - let name = tcx.hir().name(tcx.local_def_id_to_hir_id(def_id.expect_local())); + let def_id = def_id.to_def_id(); + let name = tcx.item_name(def_id); match param.kind { GenericParamKind::Lifetime { .. } => { - ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + ty::BoundVariableKind::Region(ty::BrNamed(def_id, name)) } GenericParamKind::Type { .. } => { - ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name)) + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name)) } GenericParamKind::Const { .. } => ty::BoundVariableKind::Const, } @@ -717,7 +717,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).copied(); let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; - let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) @@ -1150,7 +1149,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .param_def_id_to_index(self.tcx, region_def_id.to_def_id()) .is_some() { - break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id())); + break Some(ResolvedArg::EarlyBound(region_def_id)); } break None; } @@ -1259,7 +1258,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind => span_bug!( use_span, "did not expect to resolve lifetime to {}", - kind.descr(param_def_id) + kind.descr(param_def_id.to_def_id()) ), }; def = ResolvedArg::Error(guar); @@ -1277,10 +1276,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind: hir::ImplItemKind::Fn(..), .. }) => { - def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap()); } Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => { - def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap()); + def = ResolvedArg::Free(closure.def_id, def.id().unwrap()); } _ => {} } @@ -1351,7 +1350,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .param_def_id_to_index(self.tcx, param_def_id.to_def_id()) .is_some() { - break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id())); + break Some(ResolvedArg::EarlyBound(param_def_id)); } break None; } @@ -2072,7 +2071,7 @@ fn is_late_bound_map( } } -pub fn deny_non_region_late_bound( +fn deny_non_region_late_bound( tcx: TyCtxt<'_>, bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>, where_: &str, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8cb4ba6c669..96256b91b9f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -725,7 +725,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { } } -pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { +pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { use hir::intravisit::Visitor; if tcx.features().lazy_type_alias { return true; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index d1048b742a0..c8b0f03a929 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -331,7 +331,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, owner_def_id: LocalDefId, -) -> Ty<'_> { +) -> Ty<'tcx> { let tables = tcx.typeck(owner_def_id); // Check that all of the opaques we inferred during HIR are compatible. diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 620170164f5..edf65245664 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use rustc_type_ir::fold::TypeFoldable; #[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub struct Parameter(pub u32); +pub(crate) struct Parameter(pub u32); impl From<ty::ParamTy> for Parameter { fn from(param: ty::ParamTy) -> Self { @@ -27,7 +27,7 @@ impl From<ty::ParamConst> for Parameter { } /// Returns the set of parameters constrained by the impl header. -pub fn parameters_for_impl<'tcx>( +pub(crate) fn parameters_for_impl<'tcx>( tcx: TyCtxt<'tcx>, impl_self_ty: Ty<'tcx>, impl_trait_ref: Option<ty::TraitRef<'tcx>>, @@ -44,7 +44,7 @@ pub fn parameters_for_impl<'tcx>( /// uniquely determined by `value` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `value` - these /// differ, with the latter being a superset, in the presence of projections. -pub fn parameters_for<'tcx>( +pub(crate) fn parameters_for<'tcx>( tcx: TyCtxt<'tcx>, value: impl TypeFoldable<TyCtxt<'tcx>>, include_nonconstraining: bool, @@ -102,7 +102,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { } } -pub fn identify_constrained_generic_params<'tcx>( +pub(crate) fn identify_constrained_generic_params<'tcx>( tcx: TyCtxt<'tcx>, predicates: ty::GenericPredicates<'tcx>, impl_trait_ref: Option<ty::TraitRef<'tcx>>, @@ -156,7 +156,7 @@ pub fn identify_constrained_generic_params<'tcx>( /// which is determined by 1, which requires `U`, that is determined /// by 0. I should probably pick a less tangled example, but I can't /// think of any. -pub fn setup_constraining_predicates<'tcx>( +pub(crate) fn setup_constraining_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: &mut [(ty::Clause<'tcx>, Span)], impl_trait_ref: Option<ty::TraitRef<'tcx>>, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 821f79505f0..39df18ff658 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -11,15 +11,15 @@ use rustc_span::{Span, Symbol}; use crate::fluent_generated as fluent; mod pattern_types; -pub use pattern_types::*; -pub mod wrong_number_of_generic_args; +pub(crate) use pattern_types::*; +pub(crate) mod wrong_number_of_generic_args; mod precise_captures; pub(crate) use precise_captures::*; #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_assoc_item)] -pub struct AmbiguousAssocItem<'a> { +pub(crate) struct AmbiguousAssocItem<'a> { #[primary_span] #[label] pub span: Span, @@ -30,7 +30,7 @@ pub struct AmbiguousAssocItem<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_kind_mismatch)] -pub struct AssocKindMismatch { +pub(crate) struct AssocKindMismatch { #[primary_span] #[label] pub span: Span, @@ -52,7 +52,7 @@ pub struct AssocKindMismatch { hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, applicability = "maybe-incorrect" )] -pub struct AssocKindMismatchWrapInBracesSugg { +pub(crate) struct AssocKindMismatchWrapInBracesSugg { #[suggestion_part(code = "{{ ")] pub lo: Span, #[suggestion_part(code = " }}")] @@ -61,7 +61,7 @@ pub struct AssocKindMismatchWrapInBracesSugg { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_is_private, code = E0624)] -pub struct AssocItemIsPrivate { +pub(crate) struct AssocItemIsPrivate { #[primary_span] #[label] pub span: Span, @@ -73,7 +73,7 @@ pub struct AssocItemIsPrivate { #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_not_found, code = E0220)] -pub struct AssocItemNotFound<'a> { +pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, pub assoc_name: Ident, @@ -86,7 +86,7 @@ pub struct AssocItemNotFound<'a> { } #[derive(Subdiagnostic)] -pub enum AssocItemNotFoundLabel<'a> { +pub(crate) enum AssocItemNotFoundLabel<'a> { #[label(hir_analysis_assoc_item_not_found_label)] NotFound { #[primary_span] @@ -105,7 +105,7 @@ pub enum AssocItemNotFoundLabel<'a> { #[derive(Subdiagnostic)] -pub enum AssocItemNotFoundSugg<'a> { +pub(crate) enum AssocItemNotFoundSugg<'a> { #[suggestion( hir_analysis_assoc_item_not_found_similar_sugg, code = "{suggested_name}", @@ -162,7 +162,7 @@ pub enum AssocItemNotFoundSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_atomic_operation, code = E0092)] -pub struct UnrecognizedAtomicOperation<'a> { +pub(crate) struct UnrecognizedAtomicOperation<'a> { #[primary_span] #[label] pub span: Span, @@ -171,7 +171,7 @@ pub struct UnrecognizedAtomicOperation<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)] -pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { +pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] #[label] pub span: Span, @@ -183,7 +183,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)] #[help] -pub struct UnrecognizedIntrinsicFunction { +pub(crate) struct UnrecognizedIntrinsicFunction { #[primary_span] #[label] pub span: Span, @@ -192,7 +192,7 @@ pub struct UnrecognizedIntrinsicFunction { #[derive(Diagnostic)] #[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)] -pub struct LifetimesOrBoundsMismatchOnTrait { +pub(crate) struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] #[label] pub span: Span, @@ -208,14 +208,14 @@ pub struct LifetimesOrBoundsMismatchOnTrait { #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] -pub struct DropImplOnWrongItem { +pub(crate) struct DropImplOnWrongItem { #[primary_span] #[label] pub span: Span, } #[derive(Diagnostic)] -pub enum FieldAlreadyDeclared { +pub(crate) enum FieldAlreadyDeclared { #[diag(hir_analysis_field_already_declared, code = E0124)] NotNested { field_name: Symbol, @@ -272,14 +272,14 @@ pub enum FieldAlreadyDeclared { #[derive(Subdiagnostic)] #[help(hir_analysis_field_already_declared_nested_help)] -pub struct FieldAlreadyDeclaredNestedHelp { +pub(crate) struct FieldAlreadyDeclaredNestedHelp { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] -pub struct CopyImplOnTypeWithDtor { +pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, @@ -287,14 +287,14 @@ pub struct CopyImplOnTypeWithDtor { #[derive(Diagnostic)] #[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] -pub struct MultipleRelaxedDefaultBounds { +pub(crate) struct MultipleRelaxedDefaultBounds { #[primary_span] pub spans: Vec<Span>, } #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] -pub struct CopyImplOnNonAdt { +pub(crate) struct CopyImplOnNonAdt { #[primary_span] #[label] pub span: Span, @@ -302,7 +302,7 @@ pub struct CopyImplOnNonAdt { #[derive(Diagnostic)] #[diag(hir_analysis_const_param_ty_impl_on_unsized)] -pub struct ConstParamTyImplOnUnsized { +pub(crate) struct ConstParamTyImplOnUnsized { #[primary_span] #[label] pub span: Span, @@ -310,7 +310,7 @@ pub struct ConstParamTyImplOnUnsized { #[derive(Diagnostic)] #[diag(hir_analysis_const_param_ty_impl_on_non_adt)] -pub struct ConstParamTyImplOnNonAdt { +pub(crate) struct ConstParamTyImplOnNonAdt { #[primary_span] #[label] pub span: Span, @@ -318,7 +318,7 @@ pub struct ConstParamTyImplOnNonAdt { #[derive(Diagnostic)] #[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)] -pub struct TraitObjectDeclaredWithNoTraits { +pub(crate) struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, #[label(hir_analysis_alias_span)] @@ -327,14 +327,14 @@ pub struct TraitObjectDeclaredWithNoTraits { #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] -pub struct AmbiguousLifetimeBound { +pub(crate) struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)] -pub struct AssocItemConstraintsNotAllowedHere { +pub(crate) struct AssocItemConstraintsNotAllowedHere { #[primary_span] #[label] pub span: Span, @@ -383,7 +383,7 @@ pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> { #[derive(Subdiagnostic)] #[help(hir_analysis_parenthesized_fn_trait_expansion)] -pub struct ParenthesizedFnTraitExpansion { +pub(crate) struct ParenthesizedFnTraitExpansion { #[primary_span] pub span: Span, @@ -392,7 +392,7 @@ pub struct ParenthesizedFnTraitExpansion { #[derive(Diagnostic)] #[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)] -pub struct TypeofReservedKeywordUsed<'tcx> { +pub(crate) struct TypeofReservedKeywordUsed<'tcx> { pub ty: Ty<'tcx>, #[primary_span] #[label] @@ -403,7 +403,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)] -pub struct ValueOfAssociatedStructAlreadySpecified { +pub(crate) struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] #[label] pub span: Span, @@ -416,7 +416,7 @@ pub struct ValueOfAssociatedStructAlreadySpecified { #[derive(Diagnostic)] #[diag(hir_analysis_unconstrained_opaque_type)] #[note] -pub struct UnconstrainedOpaqueType { +pub(crate) struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, pub name: Symbol, @@ -426,7 +426,7 @@ pub struct UnconstrainedOpaqueType { #[derive(Diagnostic)] #[diag(hir_analysis_tait_forward_compat)] #[note] -pub struct TaitForwardCompat { +pub(crate) struct TaitForwardCompat { #[primary_span] pub span: Span, #[note] @@ -436,7 +436,7 @@ pub struct TaitForwardCompat { #[derive(Diagnostic)] #[diag(hir_analysis_tait_forward_compat2)] #[note] -pub struct TaitForwardCompat2 { +pub(crate) struct TaitForwardCompat2 { #[primary_span] pub span: Span, #[note(hir_analysis_opaque)] @@ -444,7 +444,7 @@ pub struct TaitForwardCompat2 { pub opaque_type: String, } -pub struct MissingTypeParams { +pub(crate) struct MissingTypeParams { pub span: Span, pub def_span: Span, pub span_snippet: Option<String>, @@ -512,7 +512,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingTypeParams { #[derive(Diagnostic)] #[diag(hir_analysis_manual_implementation, code = E0183)] #[help] -pub struct ManualImplementation { +pub(crate) struct ManualImplementation { #[primary_span] #[label] pub span: Span, @@ -521,14 +521,14 @@ pub struct ManualImplementation { #[derive(Diagnostic)] #[diag(hir_analysis_generic_args_on_overridden_impl)] -pub struct GenericArgsOnOverriddenImpl { +pub(crate) struct GenericArgsOnOverriddenImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_const_impl_for_non_const_trait)] -pub struct ConstImplForNonConstTrait { +pub(crate) struct ConstImplForNonConstTrait { #[primary_span] pub trait_ref_span: Span, pub trait_name: String, @@ -542,7 +542,7 @@ pub struct ConstImplForNonConstTrait { #[derive(Diagnostic)] #[diag(hir_analysis_const_bound_for_non_const_trait)] -pub struct ConstBoundForNonConstTrait { +pub(crate) struct ConstBoundForNonConstTrait { #[primary_span] pub span: Span, pub modifier: &'static str, @@ -550,7 +550,7 @@ pub struct ConstBoundForNonConstTrait { #[derive(Diagnostic)] #[diag(hir_analysis_self_in_impl_self)] -pub struct SelfInImplSelf { +pub(crate) struct SelfInImplSelf { #[primary_span] pub span: MultiSpan, #[note] @@ -567,7 +567,7 @@ pub(crate) struct LinkageType { #[derive(Diagnostic)] #[help] #[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)] -pub struct AutoDerefReachedRecursionLimit<'a> { +pub(crate) struct AutoDerefReachedRecursionLimit<'a> { #[primary_span] #[label] pub span: Span, @@ -736,7 +736,7 @@ pub(crate) struct InvalidUnionField { #[derive(Diagnostic)] #[diag(hir_analysis_invalid_unnamed_field_ty)] -pub struct InvalidUnnamedFieldTy { +pub(crate) struct InvalidUnnamedFieldTy { #[primary_span] pub span: Span, } @@ -894,7 +894,7 @@ pub(crate) struct SIMDFFIHighlyExperimental { } #[derive(Diagnostic)] -pub enum ImplNotMarkedDefault { +pub(crate) enum ImplNotMarkedDefault { #[diag(hir_analysis_impl_not_marked_default, code = E0520)] #[note] Ok { @@ -1137,7 +1137,7 @@ pub(crate) enum LateBoundInApit { #[derive(LintDiagnostic)] #[diag(hir_analysis_unused_associated_type_bounds)] #[note] -pub struct UnusedAssociatedTypeBounds { +pub(crate) struct UnusedAssociatedTypeBounds { #[suggestion(code = "")] pub span: Span, } @@ -1162,7 +1162,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside, code = E0390)] #[help] -pub struct InherentTyOutside { +pub(crate) struct InherentTyOutside { #[primary_span] #[help(hir_analysis_span_help)] pub span: Span, @@ -1170,7 +1170,7 @@ pub struct InherentTyOutside { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct DispatchFromDynCoercion<'a> { +pub(crate) struct DispatchFromDynCoercion<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1182,7 +1182,7 @@ pub struct DispatchFromDynCoercion<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] -pub struct DispatchFromDynRepr { +pub(crate) struct DispatchFromDynRepr { #[primary_span] pub span: Span, } @@ -1190,7 +1190,7 @@ pub struct DispatchFromDynRepr { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[help] -pub struct InherentTyOutsideRelevant { +pub(crate) struct InherentTyOutsideRelevant { #[primary_span] pub span: Span, #[help(hir_analysis_span_help)] @@ -1200,7 +1200,7 @@ pub struct InherentTyOutsideRelevant { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_new, code = E0116)] #[note] -pub struct InherentTyOutsideNew { +pub(crate) struct InherentTyOutsideNew { #[primary_span] #[label] pub span: Span, @@ -1209,7 +1209,7 @@ pub struct InherentTyOutsideNew { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)] #[help] -pub struct InherentTyOutsidePrimitive { +pub(crate) struct InherentTyOutsidePrimitive { #[primary_span] pub span: Span, #[help(hir_analysis_span_help)] @@ -1219,7 +1219,7 @@ pub struct InherentTyOutsidePrimitive { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_primitive_ty, code = E0390)] #[help] -pub struct InherentPrimitiveTy<'a> { +pub(crate) struct InherentPrimitiveTy<'a> { #[primary_span] pub span: Span, #[subdiagnostic] @@ -1228,14 +1228,14 @@ pub struct InherentPrimitiveTy<'a> { #[derive(Subdiagnostic)] #[note(hir_analysis_inherent_primitive_ty_note)] -pub struct InherentPrimitiveTyNote<'a> { +pub(crate) struct InherentPrimitiveTyNote<'a> { pub subty: Ty<'a>, } #[derive(Diagnostic)] #[diag(hir_analysis_inherent_dyn, code = E0785)] #[note] -pub struct InherentDyn { +pub(crate) struct InherentDyn { #[primary_span] #[label] pub span: Span, @@ -1244,7 +1244,7 @@ pub struct InherentDyn { #[derive(Diagnostic)] #[diag(hir_analysis_inherent_nominal, code = E0118)] #[note] -pub struct InherentNominal { +pub(crate) struct InherentNominal { #[primary_span] #[label] pub span: Span, @@ -1253,7 +1253,7 @@ pub struct InherentNominal { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)] #[note] -pub struct DispatchFromDynZST<'a> { +pub(crate) struct DispatchFromDynZST<'a> { #[primary_span] pub span: Span, pub name: Symbol, @@ -1262,7 +1262,7 @@ pub struct DispatchFromDynZST<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct DispatchFromDynSingle<'a> { +pub(crate) struct DispatchFromDynSingle<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1273,7 +1273,7 @@ pub struct DispatchFromDynSingle<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)] #[note] -pub struct DispatchFromDynMulti { +pub(crate) struct DispatchFromDynMulti { #[primary_span] pub span: Span, #[note(hir_analysis_coercions_note)] @@ -1284,7 +1284,7 @@ pub struct DispatchFromDynMulti { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0376)] -pub struct DispatchFromDynStruct<'a> { +pub(crate) struct DispatchFromDynStruct<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1292,7 +1292,7 @@ pub struct DispatchFromDynStruct<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0377)] -pub struct DispatchFromDynSame<'a> { +pub(crate) struct DispatchFromDynSame<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1304,7 +1304,7 @@ pub struct DispatchFromDynSame<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0374)] -pub struct CoerceUnsizedOneField<'a> { +pub(crate) struct CoerceUnsizedOneField<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1315,7 +1315,7 @@ pub struct CoerceUnsizedOneField<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_multi, code = E0375)] #[note] -pub struct CoerceUnsizedMulti { +pub(crate) struct CoerceUnsizedMulti { #[primary_span] #[label] pub span: Span, @@ -1327,7 +1327,7 @@ pub struct CoerceUnsizedMulti { #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0378)] -pub struct CoerceUnsizedMay<'a> { +pub(crate) struct CoerceUnsizedMay<'a> { #[primary_span] pub span: Span, pub trait_name: &'a str, @@ -1335,7 +1335,7 @@ pub struct CoerceUnsizedMay<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] -pub struct TraitCannotImplForTy { +pub(crate) struct TraitCannotImplForTy { #[primary_span] pub span: Span, pub trait_name: String, @@ -1347,7 +1347,7 @@ pub struct TraitCannotImplForTy { #[derive(Subdiagnostic)] #[note(hir_analysis_requires_note)] -pub struct ImplForTyRequires { +pub(crate) struct ImplForTyRequires { #[primary_span] pub span: MultiSpan, pub error_predicate: String, @@ -1358,7 +1358,7 @@ pub struct ImplForTyRequires { #[derive(Diagnostic)] #[diag(hir_analysis_traits_with_defualt_impl, code = E0321)] #[note] -pub struct TraitsWithDefaultImpl<'a> { +pub(crate) struct TraitsWithDefaultImpl<'a> { #[primary_span] pub span: Span, pub traits: String, @@ -1368,7 +1368,7 @@ pub struct TraitsWithDefaultImpl<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_cross_crate_traits, code = E0321)] -pub struct CrossCrateTraits<'a> { +pub(crate) struct CrossCrateTraits<'a> { #[primary_span] #[label] pub span: Span, @@ -1378,7 +1378,7 @@ pub struct CrossCrateTraits<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_cross_crate_traits_defined, code = E0321)] -pub struct CrossCrateTraitsDefined { +pub(crate) struct CrossCrateTraitsDefined { #[primary_span] #[label] pub span: Span, @@ -1390,7 +1390,7 @@ pub struct CrossCrateTraitsDefined { #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] -pub struct TyParamFirstLocal<'tcx> { +pub(crate) struct TyParamFirstLocal<'tcx> { #[primary_span] #[label] pub span: Span, @@ -1403,7 +1403,7 @@ pub struct TyParamFirstLocal<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_analysis_ty_param_first_local, code = E0210)] #[note] -pub struct TyParamFirstLocalLint<'tcx> { +pub(crate) struct TyParamFirstLocalLint<'tcx> { #[label] pub span: Span, #[note(hir_analysis_case_note)] @@ -1415,7 +1415,7 @@ pub struct TyParamFirstLocalLint<'tcx> { #[derive(Diagnostic)] #[diag(hir_analysis_ty_param_some, code = E0210)] #[note] -pub struct TyParamSome { +pub(crate) struct TyParamSome { #[primary_span] #[label] pub span: Span, @@ -1427,7 +1427,7 @@ pub struct TyParamSome { #[derive(LintDiagnostic)] #[diag(hir_analysis_ty_param_some, code = E0210)] #[note] -pub struct TyParamSomeLint { +pub(crate) struct TyParamSomeLint { #[label] pub span: Span, #[note(hir_analysis_only_note)] @@ -1436,7 +1436,7 @@ pub struct TyParamSomeLint { } #[derive(Diagnostic)] -pub enum OnlyCurrentTraits { +pub(crate) enum OnlyCurrentTraits { #[diag(hir_analysis_only_current_traits_outside, code = E0117)] Outside { #[primary_span] @@ -1465,20 +1465,20 @@ pub enum OnlyCurrentTraits { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_opaque)] -pub struct OnlyCurrentTraitsOpaque { +pub(crate) struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_foreign)] -pub struct OnlyCurrentTraitsForeign { +pub(crate) struct OnlyCurrentTraitsForeign { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_name)] -pub struct OnlyCurrentTraitsName<'a> { +pub(crate) struct OnlyCurrentTraitsName<'a> { #[primary_span] pub span: Span, pub name: &'a str, @@ -1486,7 +1486,7 @@ pub struct OnlyCurrentTraitsName<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_pointer)] -pub struct OnlyCurrentTraitsPointer<'a> { +pub(crate) struct OnlyCurrentTraitsPointer<'a> { #[primary_span] pub span: Span, pub pointer: Ty<'a>, @@ -1494,7 +1494,7 @@ pub struct OnlyCurrentTraitsPointer<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_ty)] -pub struct OnlyCurrentTraitsTy<'a> { +pub(crate) struct OnlyCurrentTraitsTy<'a> { #[primary_span] pub span: Span, pub ty: Ty<'a>, @@ -1502,7 +1502,7 @@ pub struct OnlyCurrentTraitsTy<'a> { #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_adt)] -pub struct OnlyCurrentTraitsAdt { +pub(crate) struct OnlyCurrentTraitsAdt { #[primary_span] pub span: Span, pub name: String, @@ -1513,11 +1513,11 @@ pub struct OnlyCurrentTraitsAdt { hir_analysis_only_current_traits_pointer_sugg, applicability = "maybe-incorrect" )] -pub struct OnlyCurrentTraitsPointerSugg<'a> { +pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { #[suggestion_part(code = "WrapperType")] pub wrapper_span: Span, #[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")] - pub struct_span: Span, + pub(crate) struct_span: Span, pub mut_key: &'a str, pub ptr_ty: Ty<'a>, } @@ -1525,7 +1525,7 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_static_mut_ref, code = E0796)] #[note] -pub struct StaticMutRef<'a> { +pub(crate) struct StaticMutRef<'a> { #[primary_span] #[label] pub span: Span, @@ -1535,7 +1535,7 @@ pub struct StaticMutRef<'a> { } #[derive(Subdiagnostic)] -pub enum MutRefSugg { +pub(crate) enum MutRefSugg { #[multipart_suggestion( hir_analysis_suggestion, style = "verbose", @@ -1565,7 +1565,7 @@ pub enum MutRefSugg { #[diag(hir_analysis_static_mut_refs_lint)] #[note] #[note(hir_analysis_why_note)] -pub struct RefOfMutStatic<'a> { +pub(crate) struct RefOfMutStatic<'a> { #[label] pub span: Span, #[subdiagnostic] @@ -1575,7 +1575,7 @@ pub struct RefOfMutStatic<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_not_supported_delegation)] -pub struct UnsupportedDelegation<'a> { +pub(crate) struct UnsupportedDelegation<'a> { #[primary_span] pub span: Span, pub descr: &'a str, @@ -1585,7 +1585,7 @@ pub struct UnsupportedDelegation<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_method_should_return_future)] -pub struct MethodShouldReturnFuture { +pub(crate) struct MethodShouldReturnFuture { #[primary_span] pub span: Span, pub method_name: Symbol, @@ -1649,7 +1649,7 @@ pub(crate) struct UnconstrainedGenericParameter { } #[derive(Diagnostic)] -pub enum UnnamedFieldsRepr<'a> { +pub(crate) enum UnnamedFieldsRepr<'a> { #[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)] MissingReprC { #[primary_span] @@ -1678,14 +1678,14 @@ pub enum UnnamedFieldsRepr<'a> { #[derive(Subdiagnostic)] #[note(hir_analysis_unnamed_fields_repr_field_defined)] -pub struct UnnamedFieldsReprFieldDefined { +pub(crate) struct UnnamedFieldsReprFieldDefined { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] -pub struct OpaqueCapturesHigherRankedLifetime { +pub(crate) struct OpaqueCapturesHigherRankedLifetime { #[primary_span] pub span: Span, #[label] @@ -1697,7 +1697,7 @@ pub struct OpaqueCapturesHigherRankedLifetime { #[derive(Diagnostic)] #[diag(hir_analysis_pattern_type_non_const_range)] -pub struct NonConstRange { +pub(crate) struct NonConstRange { #[primary_span] pub span: Span, } @@ -1706,7 +1706,7 @@ pub struct NonConstRange { #[diag(hir_analysis_invalid_receiver_ty, code = E0307)] #[note] #[help(hir_analysis_invalid_receiver_ty_help)] -pub struct InvalidReceiverTy<'tcx> { +pub(crate) struct InvalidReceiverTy<'tcx> { #[primary_span] pub span: Span, pub receiver_ty: Ty<'tcx>, @@ -1716,12 +1716,12 @@ pub struct InvalidReceiverTy<'tcx> { #[diag(hir_analysis_effects_without_next_solver)] #[note] #[help] -pub struct EffectsWithoutNextSolver; +pub(crate) struct EffectsWithoutNextSolver; #[derive(Diagnostic)] #[diag(hir_analysis_cmse_call_inputs_stack_spill, code = E0798)] #[note] -pub struct CmseCallInputsStackSpill { +pub(crate) struct CmseCallInputsStackSpill { #[primary_span] #[label] pub span: Span, @@ -1732,7 +1732,7 @@ pub struct CmseCallInputsStackSpill { #[diag(hir_analysis_cmse_call_output_stack_spill, code = E0798)] #[note(hir_analysis_note1)] #[note(hir_analysis_note2)] -pub struct CmseCallOutputStackSpill { +pub(crate) struct CmseCallOutputStackSpill { #[primary_span] #[label] pub span: Span, @@ -1740,7 +1740,7 @@ pub struct CmseCallOutputStackSpill { #[derive(Diagnostic)] #[diag(hir_analysis_cmse_call_generic, code = E0798)] -pub struct CmseCallGeneric { +pub(crate) struct CmseCallGeneric { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs index 008d2698989..bb771d6ea17 100644 --- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs +++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs @@ -3,7 +3,7 @@ use rustc_span::Span; #[derive(Diagnostic)] #[diag(hir_analysis_pattern_type_wild_pat)] -pub struct WildPatTy { +pub(crate) struct WildPatTy { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index 8a9b5fe6369..af2bb053c0a 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -4,7 +4,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(hir_analysis_param_not_captured)] #[note] -pub struct ParamNotCaptured { +pub(crate) struct ParamNotCaptured { #[primary_span] pub opaque_span: Span, #[label] @@ -15,7 +15,7 @@ pub struct ParamNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_self_ty_not_captured)] #[note] -pub struct SelfTyNotCaptured { +pub(crate) struct SelfTyNotCaptured { #[primary_span] pub opaque_span: Span, #[label] @@ -24,7 +24,7 @@ pub struct SelfTyNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_lifetime_not_captured)] -pub struct LifetimeNotCaptured { +pub(crate) struct LifetimeNotCaptured { #[primary_span] pub use_span: Span, #[label(hir_analysis_param_label)] @@ -35,7 +35,7 @@ pub struct LifetimeNotCaptured { #[derive(Diagnostic)] #[diag(hir_analysis_bad_precise_capture)] -pub struct BadPreciseCapture { +pub(crate) struct BadPreciseCapture { #[primary_span] pub span: Span, pub kind: &'static str, @@ -44,7 +44,7 @@ pub struct BadPreciseCapture { #[derive(Diagnostic)] #[diag(hir_analysis_precise_capture_self_alias)] -pub struct PreciseCaptureSelfAlias { +pub(crate) struct PreciseCaptureSelfAlias { #[primary_span] pub span: Span, #[label] @@ -54,7 +54,7 @@ pub struct PreciseCaptureSelfAlias { #[derive(Diagnostic)] #[diag(hir_analysis_duplicate_precise_capture)] -pub struct DuplicatePreciseCapture { +pub(crate) struct DuplicatePreciseCapture { #[primary_span] pub first_span: Span, pub name: Symbol, @@ -64,7 +64,7 @@ pub struct DuplicatePreciseCapture { #[derive(Diagnostic)] #[diag(hir_analysis_lifetime_must_be_first)] -pub struct LifetimesMustBeFirst { +pub(crate) struct LifetimesMustBeFirst { #[primary_span] pub lifetime_span: Span, pub name: Symbol, diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 8ecf53bfacb..f8b2469dfea 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -8,7 +8,7 @@ use rustc_span::def_id::DefId; use GenericArgsInfo::*; /// Handles the `wrong number of type / lifetime / ... arguments` family of error messages. -pub struct WrongNumberOfGenericArgs<'a, 'tcx> { +pub(crate) struct WrongNumberOfGenericArgs<'a, 'tcx> { pub(crate) tcx: TyCtxt<'tcx>, pub(crate) angle_brackets: AngleBrackets, @@ -49,7 +49,7 @@ pub(crate) enum AngleBrackets { // Information about the kind of arguments that are either missing or are unexpected #[derive(Debug)] -pub enum GenericArgsInfo { +pub(crate) enum GenericArgsInfo { MissingLifetimes { num_missing_args: usize, }, @@ -87,7 +87,7 @@ pub enum GenericArgsInfo { } impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { - pub fn new( + pub(crate) fn new( tcx: TyCtxt<'tcx>, gen_args_info: GenericArgsInfo, path_segment: &'a hir::PathSegment<'_>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index e99717ce00f..1b73cecd666 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -11,7 +11,7 @@ use crate::errors; /// Check conditions on inputs and outputs that the cmse ABIs impose: arguments and results MUST be /// returned via registers (i.e. MUST NOT spill to the stack). LLVM will also validate these /// conditions, but by checking them here rustc can emit nicer error messages. -pub fn validate_cmse_abi<'tcx>( +pub(crate) fn validate_cmse_abi<'tcx>( tcx: TyCtxt<'tcx>, dcx: DiagCtxtHandle<'_>, hir_id: HirId, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d77cbe30536..af319fd53bd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -608,7 +608,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 6aff518390f..7be45463f15 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -15,11 +15,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty( - &self, - self_ty: &hir::Ty<'_>, - in_path: bool, - ) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = @@ -28,6 +24,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; }; + let in_path = match tcx.parent_hir_node(self_ty.hir_id) { + hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) if qself.hir_id == self_ty.hir_id => true, + _ => false, + }; let needs_bracket = in_path && !tcx .sess diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2fb1bcf2dbf..0cdd3e4a1c6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -85,10 +85,9 @@ pub enum PredicateFilter { #[derive(Debug)] pub enum RegionInferReason<'a> { - /// Lifetime on a trait object behind a reference. - /// This allows inferring information from the reference. - BorrowedObjectLifetimeDefault, - /// A trait object's lifetime. + /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`. + ExplicitObjectLifetime, + /// A trait object's lifetime when it is elided, e.g. `dyn Any`. ObjectLifetimeDefault, /// Generic lifetime parameter Param(&'a ty::GenericParamDef), @@ -296,25 +295,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static, Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { - let name = lifetime_name(def_id.expect_local()); + let name = lifetime_name(def_id); let br = ty::BoundRegion { var: ty::BoundVar::from_u32(index), - kind: ty::BrNamed(def_id, name), + kind: ty::BrNamed(def_id.to_def_id(), name), }; ty::Region::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let name = tcx.hir().ty_param_name(def_id.expect_local()); - let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); + let name = tcx.hir().ty_param_name(def_id); + let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { - let name = lifetime_name(id.expect_local()); - ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name)) + let name = lifetime_name(id); + ty::Region::new_late_param( + tcx, + scope.to_def_id(), + ty::BrNamed(id.to_def_id(), name), + ) // (*) -- not late-bound, won't change } @@ -1053,7 +1056,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&qself_ty.kind(), qself_res) { + let bound = match (qself_ty.kind(), qself_res) { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1953,15 +1956,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); match tcx.named_bound_var(hir_id) { Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { - let name = tcx.item_name(def_id); + let name = tcx.item_name(def_id.to_def_id()); let br = ty::BoundTy { var: ty::BoundVar::from_u32(index), - kind: ty::BoundTyKind::Param(def_id, name), + kind: ty::BoundTyKind::Param(def_id.to_def_id(), name), }; Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { - let def_id = def_id.expect_local(); let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; @@ -1982,10 +1984,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::EarlyBound(def_id)) => { // Find the name and index of the const parameter by indexing the generics of // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); + let item_def_id = tcx.local_parent(def_id); let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + let name = tcx.item_name(def_id.to_def_id()); ty::Const::new_param(tcx, ty::ParamConst::new(index, name)) } Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { @@ -1996,16 +1998,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Lower a type from the HIR to our internal notion of a type. - pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, false) - } - - /// Lower a type inside of a path from the HIR to our internal notion of a type. - pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { - self.lower_ty_common(hir_ty, false, true) - } - fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { @@ -2023,7 +2015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// 2. `in_path`: Whether the type appears inside of a path. /// Used to provide correct diagnostics for bare trait object types. #[instrument(level = "debug", skip(self), ret)] - fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool) -> Ty<'tcx> { + pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match &hir_ty.kind { @@ -2033,7 +2025,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::Ref(region, mt) => { let r = self.lower_lifetime(region, RegionInferReason::Reference); debug!(?r); - let t = self.lower_ty_common(mt.ty, true, false); + let t = self.lower_ty(mt.ty); Ty::new_ref(tcx, r, t, mt.mutbl) } hir::TyKind::Never => tcx.types.never, @@ -2062,20 +2054,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); + self.prohibit_or_lint_bare_trait_object_ty(hir_ty); let repr = match repr { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.lower_trait_object_ty( - hir_ty.span, - hir_ty.hir_id, - bounds, - lifetime, - borrowed, - repr, - ) + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -2103,7 +2088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => { debug!(?qself, ?segment); - let ty = self.lower_ty_common(qself, false, true); + let ty = self.lower_ty(qself); self.lower_assoc_path(hir_ty.hir_id, hir_ty.span, ty, qself, segment, false) .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 31d1750f33d..52e167379b5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -30,7 +30,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_id: hir::HirId, hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)], lifetime: &hir::Lifetime, - borrowed: bool, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -325,22 +324,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { v.dedup(); let existential_predicates = tcx.mk_poly_existential_predicates(&v); - // Use explicitly-specified region bound. + // Use explicitly-specified region bound, unless the bound is missing. let region_bound = if !lifetime.is_elided() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { + // Curiously, we prefer object lifetime default for `+ '_`... if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) + self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { - self.re_infer( - span, - if borrowed { - RegionInferReason::ObjectLifetimeDefault + let reason = + if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res { + if let hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Ref(parent_lifetime, _), + .. + }) = tcx.parent_hir_node(hir_id) + && tcx.named_bound_var(parent_lifetime.hir_id).is_none() + { + // Parent lifetime must have failed to resolve. Don't emit a redundant error. + RegionInferReason::ExplicitObjectLifetime + } else { + RegionInferReason::ObjectLifetimeDefault + } } else { - RegionInferReason::BorrowedObjectLifetimeDefault - }, - ) + RegionInferReason::ExplicitObjectLifetime + }; + self.re_infer(span, reason) } }) }; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 7d2cabd3f2c..3ecf61501f6 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::collect::ItemCtxt; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { diagnostic_hir_wf_check, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 02520c472b9..7f183324f04 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -53,7 +53,10 @@ mod min_specialization; /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { +pub(crate) fn check_impl_wf( + tcx: TyCtxt<'_>, + impl_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; let mut res = Ok(()); debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 291d57f2a17..891e4fcd019 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -72,6 +72,7 @@ This API is completely unstable and subject to change. #![feature(slice_partition_dedup)] #![feature(try_blocks)] #![feature(unwrap_infallible)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -200,10 +201,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); - // Freeze definitions as we don't add new ones at this point. This improves performance by - // allowing lock-free access to them. - tcx.untracked().definitions.freeze(); - // FIXME: Remove this when we implement creating `DefId`s // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index bbfadbb5c30..f576499ecac 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -5,12 +5,12 @@ use rustc_middle::ty::{self, OutlivesPredicate, TyCtxt}; use super::utils::*; #[derive(Debug)] -pub struct ExplicitPredicatesMap<'tcx> { +pub(crate) struct ExplicitPredicatesMap<'tcx> { map: FxIndexMap<DefId, ty::EarlyBinder<'tcx, RequiredPredicates<'tcx>>>, } impl<'tcx> ExplicitPredicatesMap<'tcx> { - pub fn new() -> ExplicitPredicatesMap<'tcx> { + pub(crate) fn new() -> ExplicitPredicatesMap<'tcx> { ExplicitPredicatesMap { map: FxIndexMap::default() } } diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index cb61ef7c64d..e3cdb1bf5f7 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -9,7 +9,7 @@ mod explicit; mod implicit_infer; mod utils; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index ce9e73bf245..4fb7a02f8c9 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -12,7 +12,7 @@ use rustc_middle::{bug, span_bug}; use super::terms::VarianceTerm::*; use super::terms::*; -pub struct ConstraintContext<'a, 'tcx> { +pub(crate) struct ConstraintContext<'a, 'tcx> { pub terms_cx: TermsContext<'a, 'tcx>, // These are pointers to common `ConstantTerm` instances @@ -27,7 +27,7 @@ pub struct ConstraintContext<'a, 'tcx> { /// Declares that the variable `decl_id` appears in a location with /// variance `variance`. #[derive(Copy, Clone)] -pub struct Constraint<'a> { +pub(crate) struct Constraint<'a> { pub inferred: InferredIndex, pub variance: &'a VarianceTerm<'a>, } @@ -41,11 +41,11 @@ pub struct Constraint<'a> { /// ``` /// then while we are visiting `Bar<T>`, the `CurrentItem` would have /// the `DefId` and the start of `Foo`'s inferreds. -pub struct CurrentItem { +struct CurrentItem { inferred_start: InferredIndex, } -pub fn add_constraints_from_crate<'a, 'tcx>( +pub(crate) fn add_constraints_from_crate<'a, 'tcx>( terms_cx: TermsContext<'a, 'tcx>, ) -> ConstraintContext<'a, 'tcx> { let tcx = terms_cx.tcx; diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 1a17dabb677..ace183986bd 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -1,18 +1,36 @@ +use std::fmt::Write; + use rustc_hir::def::DefKind; -use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_middle::ty::TyCtxt; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_middle::ty::{GenericArgs, TyCtxt}; use rustc_span::symbol::sym; +fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { + let variances = tcx.variances_of(def_id); + let generics = GenericArgs::identity_for_item(tcx, def_id); + // 7 = 2-letter parameter + ": " + 1-letter variance + ", " + let mut ret = String::with_capacity(2 + 7 * variances.len()); + ret.push('['); + for (arg, variance) in generics.iter().zip(variances.iter()) { + write!(ret, "{arg}: {variance:?}, ").unwrap(); + } + // Remove trailing `, `. + if !variances.is_empty() { + ret.pop(); + ret.pop(); + } + ret.push(']'); + ret +} + pub(crate) fn variances(tcx: TyCtxt<'_>) { if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue }; - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } @@ -22,11 +40,9 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) { continue; } - let variances = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), - variances: format!("{variances:?}"), + variances: format_variances(tcx, id.owner_id.def_id), }); } } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 8a4114c3e4b..e8e2caf7e62 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -28,7 +28,7 @@ pub(crate) mod dump; /// Code for transforming variances. mod xform; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { variances_of, crate_variances, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs index e64c6721fe0..4f1bac17e71 100644 --- a/compiler/rustc_hir_analysis/src/variance/solve.rs +++ b/compiler/rustc_hir_analysis/src/variance/solve.rs @@ -21,7 +21,7 @@ struct SolveContext<'a, 'tcx> { solutions: Vec<ty::Variance>, } -pub fn solve_constraints<'tcx>( +pub(crate) fn solve_constraints<'tcx>( constraints_cx: ConstraintContext<'_, 'tcx>, ) -> ty::CrateVariancesMap<'tcx> { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 36bff60e019..597699b37b1 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -18,13 +18,13 @@ use rustc_middle::ty::{self, TyCtxt}; use self::VarianceTerm::*; -pub type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; +pub(crate) type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; #[derive(Copy, Clone, Debug)] -pub struct InferredIndex(pub usize); +pub(crate) struct InferredIndex(pub usize); #[derive(Copy, Clone)] -pub enum VarianceTerm<'a> { +pub(crate) enum VarianceTerm<'a> { ConstantTerm(ty::Variance), TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>), InferredTerm(InferredIndex), @@ -45,7 +45,7 @@ impl<'a> fmt::Debug for VarianceTerm<'a> { /// The first pass over the crate simply builds up the set of inferreds. -pub struct TermsContext<'a, 'tcx> { +pub(crate) struct TermsContext<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub arena: &'a DroplessArena, @@ -62,7 +62,7 @@ pub struct TermsContext<'a, 'tcx> { pub inferred_terms: Vec<VarianceTermPtr<'a>>, } -pub fn determine_parameters_to_be_inferred<'a, 'tcx>( +pub(crate) fn determine_parameters_to_be_inferred<'a, 'tcx>( tcx: TyCtxt<'tcx>, arena: &'a DroplessArena, ) -> TermsContext<'a, 'tcx> { diff --git a/compiler/rustc_hir_analysis/src/variance/xform.rs b/compiler/rustc_hir_analysis/src/variance/xform.rs index 027f0859fcd..2e9964788e6 100644 --- a/compiler/rustc_hir_analysis/src/variance/xform.rs +++ b/compiler/rustc_hir_analysis/src/variance/xform.rs @@ -1,6 +1,6 @@ use rustc_middle::ty; -pub fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { +pub(crate) fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { // Greatest lower bound of the variance lattice as // defined in The Paper: // diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index cff21173f79..ac6707f9316 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::Cell; diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index bc0ed4a7fa9..7427fb14716 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn maybe_get_coercion_reason( + pub(crate) fn maybe_get_coercion_reason( &self, hir_id: hir::HirId, sp: Span, @@ -584,7 +584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // (e.g. we're in the tail of a function body) // // Returns the `LocalDefId` of the RPIT, which is always identity-substituted. - pub fn return_position_impl_trait_from_match_expectation( + pub(crate) fn return_position_impl_trait_from_match_expectation( &self, expectation: Expectation<'tcx>, ) -> Option<LocalDefId> { diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 69c4889d7a4..d2d6da8f32b 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -13,11 +13,11 @@ use super::method::MethodCallee; use super::{FnCtxt, PlaceOp}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { + pub(crate) fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { Autoderef::new(self, self.param_env, self.body_id, span, base_ty) } - pub fn try_overloaded_deref( + pub(crate) fn try_overloaded_deref( &self, span: Span, base_ty: Ty<'tcx>, @@ -26,11 +26,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Returns the adjustment steps. - pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> { + pub(crate) fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> { self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef)) } - pub fn adjust_steps_as_infer_ok( + pub(crate) fn adjust_steps_as_infer_ok( &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 44cb08e44eb..fc08b872efc 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -29,7 +29,7 @@ use crate::errors; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific /// method that is called). -pub fn check_legal_trait_for_method_call( +pub(crate) fn check_legal_trait_for_method_call( tcx: TyCtxt<'_>, span: Span, receiver: Option<Span>, @@ -62,7 +62,7 @@ enum CallStep<'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_call( + pub(crate) fn check_call( &self, call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, @@ -940,7 +940,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[derive(Debug)] -pub struct DeferredCallResolution<'tcx> { +pub(crate) struct DeferredCallResolution<'tcx> { call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, closure_ty: Ty<'tcx>, @@ -949,7 +949,7 @@ pub struct DeferredCallResolution<'tcx> { } impl<'a, 'tcx> DeferredCallResolution<'tcx> { - pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { + pub(crate) fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { debug!("DeferredCallResolution::resolve() {:?}", self); // we should not be invoked until the closure kind has been diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9b34c59f1f1..54ddff98869 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -106,7 +106,7 @@ fn identity(_: Ty<'_>) -> Vec<Adjustment<'_>> { vec![] } -fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'_>> { +fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>> { move |target| vec![Adjustment { kind, target }] } @@ -850,6 +850,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). + // FIXME(struct_target_features): should this be true also for functions that inherit + // target features from structs? if b_hdr.safety == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() @@ -976,7 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// adjusted type of the expression, if successful. /// Adjustments are only recorded if the coercion succeeded. /// The expressions *must not* have any preexisting adjustments. - pub fn coerce( + pub(crate) fn coerce( &self, expr: &hir::Expr<'_>, expr_ty: Ty<'tcx>, @@ -1011,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// Returns false if the coercion creates any obligations that result in /// errors. - pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { + pub(crate) fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { // FIXME(-Znext-solver): We need to structurally resolve both types here. let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); @@ -1032,7 +1034,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a type and a target type, this function will calculate and return /// how many dereference steps needed to achieve `expr_ty <: target`. If /// it's not possible, return `None`. - pub fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> { + pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option<usize> { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); @@ -1047,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This function is for diagnostics only, since it does not register /// trait or region sub-obligations. (presumably we could, but it's not /// particularly important for diagnostics...) - pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> { + pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> { self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| { self.infcx .type_implements_trait( @@ -1341,7 +1343,7 @@ pub fn can_coerce<'tcx>( /// } /// let final_ty = coerce.complete(fcx); /// ``` -pub struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { +pub(crate) struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { expected_ty: Ty<'tcx>, final_ty: Option<Ty<'tcx>>, expressions: Expressions<'tcx, 'exprs, E>, @@ -1350,7 +1352,7 @@ pub struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> { /// The type of a `CoerceMany` that is storing up the expressions into /// a buffer. We use this in `check/mod.rs` for things like `break`. -pub type DynamicCoerceMany<'tcx> = CoerceMany<'tcx, 'tcx, &'tcx hir::Expr<'tcx>>; +pub(crate) type DynamicCoerceMany<'tcx> = CoerceMany<'tcx, 'tcx, &'tcx hir::Expr<'tcx>>; enum Expressions<'tcx, 'exprs, E: AsCoercionSite> { Dynamic(Vec<&'tcx hir::Expr<'tcx>>), @@ -1361,7 +1363,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// The usual case; collect the set of expressions dynamically. /// If the full set of coercion sites is known before hand, /// consider `with_coercion_sites()` instead to avoid allocation. - pub fn new(expected_ty: Ty<'tcx>) -> Self { + pub(crate) fn new(expected_ty: Ty<'tcx>) -> Self { Self::make(expected_ty, Expressions::Dynamic(vec![])) } @@ -1370,7 +1372,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// expected to pass each element in the slice to `coerce(...)` in /// order. This is used with arrays in particular to avoid /// needlessly cloning the slice. - pub fn with_coercion_sites(expected_ty: Ty<'tcx>, coercion_sites: &'exprs [E]) -> Self { + pub(crate) fn with_coercion_sites(expected_ty: Ty<'tcx>, coercion_sites: &'exprs [E]) -> Self { Self::make(expected_ty, Expressions::UpFront(coercion_sites)) } @@ -1386,7 +1388,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// Typically, this is used as the expected type when /// type-checking each of the alternative expressions whose types /// we are trying to merge. - pub fn expected_ty(&self) -> Ty<'tcx> { + pub(crate) fn expected_ty(&self) -> Ty<'tcx> { self.expected_ty } @@ -1394,7 +1396,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// at the LUB of the expressions we've seen so far (if any). This /// isn't *final* until you call `self.complete()`, which will return /// the merged type. - pub fn merged_ty(&self) -> Ty<'tcx> { + pub(crate) fn merged_ty(&self) -> Ty<'tcx> { self.final_ty.unwrap_or(self.expected_ty) } @@ -1403,7 +1405,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// could coerce from. This will record `expression`, and later /// calls to `coerce` may come back and add adjustments and things /// if necessary. - pub fn coerce<'a>( + pub(crate) fn coerce<'a>( &mut self, fcx: &FnCtxt<'a, 'tcx>, cause: &ObligationCause<'tcx>, @@ -1425,7 +1427,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// The `augment_error` gives you a chance to extend the error /// message, in case any results (e.g., we use this to suggest /// removing a `;`). - pub fn coerce_forced_unit<'a>( + pub(crate) fn coerce_forced_unit<'a>( &mut self, fcx: &FnCtxt<'a, 'tcx>, cause: &ObligationCause<'tcx>, @@ -1920,7 +1922,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } } - pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { + pub(crate) fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> { if let Some(final_ty) = self.final_ty { final_ty } else { @@ -1934,7 +1936,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { /// Something that can be converted into an expression to which we can /// apply a coercion. -pub trait AsCoercionSite { +pub(crate) trait AsCoercionSite { fn as_coercion_site(&self) -> &hir::Expr<'_>; } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0a9fa5c64a5..89f27e80774 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -18,7 +18,7 @@ use super::method::probe; use crate::FnCtxt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn emit_type_mismatch_suggestions( + pub(crate) fn emit_type_mismatch_suggestions( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -70,7 +70,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn emit_coerce_suggestions( + pub(crate) fn emit_coerce_suggestions( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -165,13 +165,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Requires that the two types unify, and prints an error message if /// they don't. - pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + pub(crate) fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Err(e) = self.demand_suptype_diag(sp, expected, actual) { e.emit(); } } - pub fn demand_suptype_diag( + pub(crate) fn demand_suptype_diag( &'a self, sp: Span, expected: Ty<'tcx>, @@ -193,13 +193,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) } - pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) { err.emit(); } } - pub fn demand_eqtype_diag( + pub(crate) fn demand_eqtype_diag( &'a self, sp: Span, expected: Ty<'tcx>, @@ -208,7 +208,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_with_origin(&self.misc(sp), expected, actual) } - pub fn demand_eqtype_with_origin( + pub(crate) fn demand_eqtype_with_origin( &'a self, cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, @@ -220,7 +220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) } - pub fn demand_coerce( + pub(crate) fn demand_coerce( &self, expr: &'tcx hir::Expr<'tcx>, checked_ty: Ty<'tcx>, @@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Notes the point at which a variable is constrained to some type incompatible /// with some expectation given by `source`. - pub fn note_source_of_type_mismatch_constraint( + pub(crate) fn note_source_of_type_mismatch_constraint( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -558,7 +558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // When encountering a type error on the value of a `break`, try to point at the reason for the // expected type. - pub fn annotate_loop_expected_due_to_inference( + pub(crate) fn annotate_loop_expected_due_to_inference( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -964,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - pub fn get_conversion_methods_for_diagnostic( + pub(crate) fn get_conversion_methods_for_diagnostic( &self, span: Span, expected: Ty<'tcx>, @@ -1186,7 +1186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -pub enum TypeMismatchSource<'tcx> { +pub(crate) enum TypeMismatchSource<'tcx> { /// Expected the binding to have the given type, but it was found to have /// a different type. Find out when that type first became incompatible. Ty(Ty<'tcx>), diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs index aa30fb0f0af..3066561a31d 100644 --- a/compiler/rustc_hir_typeck/src/diverges.rs +++ b/compiler/rustc_hir_typeck/src/diverges.rs @@ -8,7 +8,7 @@ use rustc_span::{Span, DUMMY_SP}; /// as diverging), with some manual adjustments for control-flow /// primitives (approximating a CFG). #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Diverges { +pub(crate) enum Diverges { /// Potentially unknown, some cases converge, /// others require a CFG to determine them. Maybe, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index c35f7a84c4f..4d2770d2e50 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -17,7 +17,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] -pub struct FieldMultiplySpecifiedInInitializer { +pub(crate) struct FieldMultiplySpecifiedInInitializer { #[primary_span] #[label] pub span: Span, @@ -28,7 +28,7 @@ pub struct FieldMultiplySpecifiedInInitializer { #[derive(Diagnostic)] #[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)] -pub struct ReturnStmtOutsideOfFnBody { +pub(crate) struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, #[label(hir_typeck_encl_body_label)] @@ -38,7 +38,7 @@ pub struct ReturnStmtOutsideOfFnBody { pub statement_kind: ReturnLikeStatementKind, } -pub enum ReturnLikeStatementKind { +pub(crate) enum ReturnLikeStatementKind { Return, Become, } @@ -57,21 +57,21 @@ impl IntoDiagArg for ReturnLikeStatementKind { #[derive(Diagnostic)] #[diag(hir_typeck_rustcall_incorrect_args)] -pub struct RustCallIncorrectArgs { +pub(crate) struct RustCallIncorrectArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)] -pub struct YieldExprOutsideOfCoroutine { +pub(crate) struct YieldExprOutsideOfCoroutine { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)] -pub struct StructExprNonExhaustive { +pub(crate) struct StructExprNonExhaustive { #[primary_span] pub span: Span, pub what: &'static str, @@ -79,21 +79,21 @@ pub struct StructExprNonExhaustive { #[derive(Diagnostic)] #[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] -pub struct FunctionalRecordUpdateOnNonStruct { +pub(crate) struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_address_of_temporary_taken, code = E0745)] -pub struct AddressOfTemporaryTaken { +pub(crate) struct AddressOfTemporaryTaken { #[primary_span] #[label] pub span: Span, } #[derive(Subdiagnostic)] -pub enum AddReturnTypeSuggestion { +pub(crate) enum AddReturnTypeSuggestion { #[suggestion( hir_typeck_add_return_type_add, code = " -> {found}", @@ -116,7 +116,7 @@ pub enum AddReturnTypeSuggestion { } #[derive(Subdiagnostic)] -pub enum ExpectedReturnTypeLabel<'tcx> { +pub(crate) enum ExpectedReturnTypeLabel<'tcx> { #[label(hir_typeck_expected_default_return_type)] Unit { #[primary_span] @@ -132,7 +132,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_explicit_destructor, code = E0040)] -pub struct ExplicitDestructorCall { +pub(crate) struct ExplicitDestructorCall { #[primary_span] #[label] pub span: Span, @@ -141,7 +141,7 @@ pub struct ExplicitDestructorCall { } #[derive(Subdiagnostic)] -pub enum ExplicitDestructorCallSugg { +pub(crate) enum ExplicitDestructorCallSugg { #[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")] Empty(#[primary_span] Span), #[multipart_suggestion(hir_typeck_suggestion, style = "short")] @@ -155,7 +155,7 @@ pub enum ExplicitDestructorCallSugg { #[derive(Diagnostic)] #[diag(hir_typeck_missing_parentheses_in_range, code = E0689)] -pub struct MissingParenthesesInRange { +pub(crate) struct MissingParenthesesInRange { #[primary_span] #[label(hir_typeck_missing_parentheses_in_range)] pub span: Span, @@ -166,7 +166,7 @@ pub struct MissingParenthesesInRange { } #[derive(LintDiagnostic)] -pub enum NeverTypeFallbackFlowingIntoUnsafe { +pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { #[help] #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)] Call, @@ -187,7 +187,7 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe { #[derive(LintDiagnostic)] #[help] #[diag(hir_typeck_dependency_on_unit_never_type_fallback)] -pub struct DependencyOnUnitNeverTypeFallback<'tcx> { +pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> { #[note] pub obligation_span: Span, pub obligation: ty::Predicate<'tcx>, @@ -199,7 +199,7 @@ pub struct DependencyOnUnitNeverTypeFallback<'tcx> { style = "verbose", applicability = "maybe-incorrect" )] -pub struct AddMissingParenthesesInRange { +pub(crate) struct AddMissingParenthesesInRange { pub func_name: String, #[suggestion_part(code = "(")] pub left: Span, @@ -207,7 +207,7 @@ pub struct AddMissingParenthesesInRange { pub right: Span, } -pub struct TypeMismatchFruTypo { +pub(crate) struct TypeMismatchFruTypo { /// Span of the LHS of the range pub expr_span: Span, /// Span of the `..RHS` part of the range @@ -246,7 +246,7 @@ impl Subdiagnostic for TypeMismatchFruTypo { #[derive(LintDiagnostic)] #[diag(hir_typeck_lossy_provenance_int2ptr)] #[help] -pub struct LossyProvenanceInt2Ptr<'tcx> { +pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[subdiagnostic] @@ -255,14 +255,14 @@ pub struct LossyProvenanceInt2Ptr<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_typeck_ptr_cast_add_auto_to_object)] -pub struct PtrCastAddAutoToObject { +pub(crate) struct PtrCastAddAutoToObject { pub traits_len: usize, pub traits: DiagSymbolList<String>, } #[derive(Subdiagnostic)] #[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")] -pub struct LossyProvenanceInt2PtrSuggestion { +pub(crate) struct LossyProvenanceInt2PtrSuggestion { #[suggestion_part(code = "(...).with_addr(")] pub lo: Span, #[suggestion_part(code = ")")] @@ -272,7 +272,7 @@ pub struct LossyProvenanceInt2PtrSuggestion { #[derive(LintDiagnostic)] #[diag(hir_typeck_lossy_provenance_ptr2int)] #[help] -pub struct LossyProvenancePtr2Int<'tcx> { +pub(crate) struct LossyProvenancePtr2Int<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[subdiagnostic] @@ -280,7 +280,7 @@ pub struct LossyProvenancePtr2Int<'tcx> { } #[derive(Subdiagnostic)] -pub enum LossyProvenancePtr2IntSuggestion<'tcx> { +pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] NeedsParensCast { #[suggestion_part(code = "(")] @@ -314,7 +314,7 @@ pub enum LossyProvenancePtr2IntSuggestion<'tcx> { } #[derive(Subdiagnostic)] -pub enum HelpUseLatestEdition { +pub(crate) enum HelpUseLatestEdition { #[help(hir_typeck_help_set_edition_cargo)] #[note(hir_typeck_note_edition_guide)] Cargo { edition: Edition }, @@ -324,7 +324,7 @@ pub enum HelpUseLatestEdition { } impl HelpUseLatestEdition { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let edition = LATEST_STABLE_EDITION; if rustc_session::utils::was_invoked_from_cargo() { Self::Cargo { edition } @@ -336,7 +336,7 @@ impl HelpUseLatestEdition { #[derive(Diagnostic)] #[diag(hir_typeck_invalid_callee, code = E0618)] -pub struct InvalidCallee { +pub(crate) struct InvalidCallee { #[primary_span] pub span: Span, pub ty: String, @@ -344,7 +344,7 @@ pub struct InvalidCallee { #[derive(Diagnostic)] #[diag(hir_typeck_int_to_fat, code = E0606)] -pub struct IntToWide<'tcx> { +pub(crate) struct IntToWide<'tcx> { #[primary_span] #[label(hir_typeck_int_to_fat_label)] pub span: Span, @@ -357,7 +357,7 @@ pub struct IntToWide<'tcx> { } #[derive(Subdiagnostic)] -pub enum OptionResultRefMismatch { +pub(crate) enum OptionResultRefMismatch { #[suggestion( hir_typeck_option_result_copied, code = ".copied()", @@ -396,7 +396,7 @@ pub enum OptionResultRefMismatch { // }, } -pub struct RemoveSemiForCoerce { +pub(crate) struct RemoveSemiForCoerce { pub expr: Span, pub ret: Span, pub semi: Span, @@ -426,7 +426,7 @@ impl Subdiagnostic for RemoveSemiForCoerce { #[derive(Diagnostic)] #[diag(hir_typeck_const_select_must_be_const)] #[help] -pub struct ConstSelectMustBeConst { +pub(crate) struct ConstSelectMustBeConst { #[primary_span] pub span: Span, } @@ -435,7 +435,7 @@ pub struct ConstSelectMustBeConst { #[diag(hir_typeck_const_select_must_be_fn)] #[note] #[help] -pub struct ConstSelectMustBeFn<'a> { +pub(crate) struct ConstSelectMustBeFn<'a> { #[primary_span] pub span: Span, pub ty: Ty<'a>, @@ -443,14 +443,14 @@ pub struct ConstSelectMustBeFn<'a> { #[derive(Diagnostic)] #[diag(hir_typeck_union_pat_multiple_fields)] -pub struct UnionPatMultipleFields { +pub(crate) struct UnionPatMultipleFields { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(hir_typeck_union_pat_dotdot)] -pub struct UnionPatDotDot { +pub(crate) struct UnionPatDotDot { #[primary_span] pub span: Span, } @@ -461,7 +461,7 @@ pub struct UnionPatDotDot { applicability = "maybe-incorrect", style = "verbose" )] -pub struct UseIsEmpty { +pub(crate) struct UseIsEmpty { #[suggestion_part(code = "!")] pub lo: Span, #[suggestion_part(code = ".is_empty()")] @@ -471,13 +471,13 @@ pub struct UseIsEmpty { #[derive(Diagnostic)] #[diag(hir_typeck_arg_mismatch_indeterminate)] -pub struct ArgMismatchIndeterminate { +pub(crate) struct ArgMismatchIndeterminate { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -pub enum SuggestBoxing { +pub(crate) enum SuggestBoxing { #[note(hir_typeck_suggest_boxing_note)] #[multipart_suggestion( hir_typeck_suggest_boxing_when_appropriate, @@ -511,7 +511,7 @@ pub enum SuggestBoxing { style = "verbose", code = "core::ptr::null_mut()" )] -pub struct SuggestPtrNullMut { +pub(crate) struct SuggestPtrNullMut { #[primary_span] pub span: Span, } @@ -519,7 +519,7 @@ pub struct SuggestPtrNullMut { #[derive(LintDiagnostic)] #[diag(hir_typeck_trivial_cast)] #[help] -pub struct TrivialCast<'tcx> { +pub(crate) struct TrivialCast<'tcx> { pub numeric: bool, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -527,7 +527,7 @@ pub struct TrivialCast<'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_no_associated_item, code = E0599)] -pub struct NoAssociatedItem { +pub(crate) struct NoAssociatedItem { #[primary_span] pub span: Span, pub item_kind: &'static str, @@ -539,7 +539,7 @@ pub struct NoAssociatedItem { #[derive(Subdiagnostic)] #[note(hir_typeck_candidate_trait_note)] -pub struct CandidateTraitNote { +pub(crate) struct CandidateTraitNote { #[primary_span] pub span: Span, pub trait_name: String, @@ -549,7 +549,7 @@ pub struct CandidateTraitNote { #[derive(Diagnostic)] #[diag(hir_typeck_cannot_cast_to_bool, code = E0054)] -pub struct CannotCastToBool<'tcx> { +pub(crate) struct CannotCastToBool<'tcx> { #[primary_span] pub span: Span, pub expr_ty: Ty<'tcx>, @@ -559,14 +559,14 @@ pub struct CannotCastToBool<'tcx> { #[derive(LintDiagnostic)] #[diag(hir_typeck_cast_enum_drop)] -pub struct CastEnumDrop<'tcx> { +pub(crate) struct CastEnumDrop<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(hir_typeck_cast_unknown_pointer, code = E0641)] -pub struct CastUnknownPointer { +pub(crate) struct CastUnknownPointer { #[primary_span] pub span: Span, pub to: bool, @@ -574,7 +574,7 @@ pub struct CastUnknownPointer { pub sub: CastUnknownPointerSub, } -pub enum CastUnknownPointerSub { +pub(crate) enum CastUnknownPointerSub { To(Span), From(Span), } @@ -601,7 +601,7 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { } #[derive(Subdiagnostic)] -pub enum CannotCastToBoolHelp { +pub(crate) enum CannotCastToBoolHelp { #[suggestion( hir_typeck_suggestion, applicability = "machine-applicable", @@ -615,7 +615,7 @@ pub enum CannotCastToBoolHelp { #[derive(Diagnostic)] #[diag(hir_typeck_ctor_is_private, code = E0603)] -pub struct CtorIsPrivate { +pub(crate) struct CtorIsPrivate { #[primary_span] pub span: Span, pub def: String, @@ -623,7 +623,7 @@ pub struct CtorIsPrivate { #[derive(Subdiagnostic)] #[note(hir_typeck_deref_is_empty)] -pub struct DerefImplsIsEmpty { +pub(crate) struct DerefImplsIsEmpty { #[primary_span] pub span: Span, pub deref_ty: String, @@ -635,7 +635,7 @@ pub struct DerefImplsIsEmpty { applicability = "machine-applicable", style = "verbose" )] -pub struct SuggestConvertViaMethod<'tcx> { +pub(crate) struct SuggestConvertViaMethod<'tcx> { #[suggestion_part(code = "{sugg}")] pub span: Span, #[suggestion_part(code = "")] @@ -647,13 +647,13 @@ pub struct SuggestConvertViaMethod<'tcx> { #[derive(Subdiagnostic)] #[note(hir_typeck_note_caller_chooses_ty_for_ty_param)] -pub struct NoteCallerChoosesTyForTyParam<'tcx> { +pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { pub ty_param_name: Symbol, pub found_ty: Ty<'tcx>, } #[derive(Subdiagnostic)] -pub enum SuggestBoxingForReturnImplTrait { +pub(crate) enum SuggestBoxingForReturnImplTrait { #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")] ChangeReturnType { #[suggestion_part(code = "Box<dyn")] @@ -672,7 +672,7 @@ pub enum SuggestBoxingForReturnImplTrait { #[derive(Diagnostic)] #[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)] -pub struct SelfCtorFromOuterItem { +pub(crate) struct SelfCtorFromOuterItem { #[primary_span] pub span: Span, #[label] @@ -683,7 +683,7 @@ pub struct SelfCtorFromOuterItem { #[derive(LintDiagnostic)] #[diag(hir_typeck_self_ctor_from_outer_item)] -pub struct SelfCtorFromOuterItemLint { +pub(crate) struct SelfCtorFromOuterItemLint { #[label] pub impl_span: Span, #[subdiagnostic] @@ -692,7 +692,7 @@ pub struct SelfCtorFromOuterItemLint { #[derive(Subdiagnostic)] #[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")] -pub struct ReplaceWithName { +pub(crate) struct ReplaceWithName { #[primary_span] pub span: Span, pub name: String, diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 76ae41db5c5..67f4dbee3cb 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -7,7 +7,7 @@ use super::FnCtxt; /// When type-checking an expression, we propagate downward /// whatever type hint we are able in the form of an `Expectation`. #[derive(Copy, Clone, Debug)] -pub enum Expectation<'tcx> { +pub(crate) enum Expectation<'tcx> { /// We know nothing about what type this expression should have. NoExpectation, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fec6efdc0f7..dd33b947b0d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -51,7 +51,7 @@ use crate::{ }; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_expr_has_type_or_error( + pub(crate) fn check_expr_has_type_or_error( &self, expr: &'tcx hir::Expr<'tcx>, expected_ty: Ty<'tcx>, @@ -841,6 +841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); let mut span = return_expr.span; + let mut hir_id = return_expr.hir_id; // Use the span of the trailing expression for our cause, // not the span of the entire function if !explicit_return @@ -848,6 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(last_expr) = body.expr { span = last_expr.span; + hir_id = last_expr.hir_id; } ret_coercion.borrow_mut().coerce( self, @@ -864,6 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.select_obligations_where_possible(|errors| { self.point_at_return_for_opaque_ty_error( errors, + hir_id, span, return_expr_ty, return_expr.span, @@ -921,6 +924,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn point_at_return_for_opaque_ty_error( &self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, + hir_id: HirId, span: Span, return_expr_ty: Ty<'tcx>, return_span: Span, @@ -935,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let new_cause = ObligationCause::new( cause.span, cause.body_id, - ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), + ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, hir_id))), ); *cause = new_cause; } @@ -973,7 +977,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Check if the expression that could not be assigned to was a typoed expression that - pub fn check_for_missing_semi(&self, expr: &'tcx hir::Expr<'tcx>, err: &mut Diag<'_>) -> bool { + pub(crate) fn check_for_missing_semi( + &self, + expr: &'tcx hir::Expr<'tcx>, + err: &mut Diag<'_>, + ) -> bool { if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind && let hir::BinOpKind::Mul = binop.node && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span)) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 6e1b7504626..b1dc19b3777 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -18,7 +18,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use crate::{errors, FnCtxt, TypeckRootCtxt}; #[derive(Copy, Clone)] -pub enum DivergingFallbackBehavior { +pub(crate) enum DivergingFallbackBehavior { /// Always fallback to `()` (aka "always spontaneous decay") ToUnit, /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b169f75796b..2d205d1ede9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -132,18 +132,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default() } - pub fn tag(&self) -> String { + fn tag(&self) -> String { format!("{self:p}") } - pub fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> { + pub(crate) fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> { self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| { span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid)) }) } #[inline] - pub fn write_ty(&self, id: HirId, ty: Ty<'tcx>) { + pub(crate) fn write_ty(&self, id: HirId, ty: Ty<'tcx>) { debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_vars_if_possible(ty), self.tag()); let mut typeck = self.typeck_results.borrow_mut(); let mut node_ty = typeck.node_types_mut(); @@ -165,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn write_field_index( + pub(crate) fn write_field_index( &self, hir_id: HirId, index: FieldIdx, @@ -198,7 +198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_args(hir_id, method.args); } - pub fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) { + fn write_args(&self, node_id: HirId, args: GenericArgsRef<'tcx>) { if !args.is_empty() { debug!("write_args({:?}, {:?}) in fcx {}", node_id, args, self.tag()); @@ -364,7 +364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - pub fn require_type_meets( + pub(crate) fn require_type_meets( &self, ty: Ty<'tcx>, span: Span, @@ -374,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_bound(ty, def_id, traits::ObligationCause::new(span, self.body_id, code)); } - pub fn require_type_is_sized( + pub(crate) fn require_type_is_sized( &self, ty: Ty<'tcx>, span: Span, @@ -386,7 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn require_type_is_sized_deferred( + pub(crate) fn require_type_is_sized_deferred( &self, ty: Ty<'tcx>, span: Span, @@ -397,7 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn require_type_has_static_alignment( + pub(crate) fn require_type_has_static_alignment( &self, ty: Ty<'tcx>, span: Span, @@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn register_bound( + pub(crate) fn register_bound( &self, ty: Ty<'tcx>, def_id: DefId, @@ -443,7 +443,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> { + pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> LoweredTy<'tcx> { let ty = self.lowerer().lower_ty(hir_ty); self.register_wf_obligation(ty.into(), hir_ty.span, ObligationCauseCode::WellFormed(None)); LoweredTy::from_raw(self, hir_ty.span, ty) @@ -474,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { + pub(crate) fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), hir::ArrayLen::Body(const_arg) => { @@ -486,7 +486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_const_arg( + pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, param_def_id: DefId, @@ -515,7 +515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { t.has_free_regions() || t.has_aliases() || t.has_infer_types() } - pub fn node_ty(&self, id: HirId) -> Ty<'tcx> { + pub(crate) fn node_ty(&self, id: HirId) -> Ty<'tcx> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => t, None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e), @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn node_ty_opt(&self, id: HirId) -> Option<Ty<'tcx>> { + pub(crate) fn node_ty_opt(&self, id: HirId) -> Option<Ty<'tcx>> { match self.typeck_results.borrow().node_types().get(id) { Some(&t) => Some(t), None if let Some(e) = self.tainted_by_errors() => Some(Ty::new_error(self.tcx, e)), @@ -538,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Registers an obligation for checking later, during regionck, that `arg` is well-formed. - pub fn register_wf_obligation( + pub(crate) fn register_wf_obligation( &self, arg: ty::GenericArg<'tcx>, span: Span, @@ -555,7 +555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Registers obligations that all `args` are well-formed. - pub fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) { + pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) { for arg in args.iter().filter(|arg| { matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) }) { @@ -566,7 +566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(arielb1): use this instead of field.ty everywhere // Only for fields! Returns <none> for methods> // Indifferent to privacy flags - pub fn field_ty( + pub(crate) fn field_ty( &self, span: Span, field: &'tcx ty::FieldDef, @@ -798,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - let ty = self.lowerer().lower_ty_in_path(qself); + let ty = self.lowerer().lower_ty(qself); (LoweredTy::from_raw(self, span, ty), qself, segment) } QPath::LangItem(..) => { @@ -897,7 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a /// suggestion can be made, `None` otherwise. - pub fn get_fn_decl( + pub(crate) fn get_fn_decl( &self, blk_id: HirId, ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { @@ -1534,7 +1534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// If no resolution is possible, then an error is reported. /// Numeric inference variables may be left unresolved. - pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { + pub(crate) fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = self.try_structurally_resolve_type(sp, ty); if !ty.is_ty_var() { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 130fd130ec8..a8ba9f139cc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -12,7 +12,7 @@ use rustc_trait_selection::traits; use crate::FnCtxt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn adjust_fulfillment_error_for_expr_obligation( + pub(crate) fn adjust_fulfillment_error_for_expr_obligation( &self, error: &mut traits::FulfillmentError<'tcx>, ) -> bool { @@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { * * This function only updates the error span. */ - pub fn blame_specific_expr_if_possible( + pub(crate) fn blame_specific_expr_if_possible( &self, error: &mut traits::FulfillmentError<'tcx>, expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index 78895689433..cb77d3f85d9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -17,7 +17,7 @@ rustc_index::newtype_index! { } impl ExpectedIdx { - pub fn to_provided_idx(self) -> ProvidedIdx { + pub(crate) fn to_provided_idx(self) -> ProvidedIdx { ProvidedIdx::from_usize(self.as_usize()) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index aca29d47587..5333982c420 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -45,7 +45,7 @@ use crate::{ }; #[derive(Clone, Copy, Default)] -pub enum DivergingBlockBehavior { +pub(crate) enum DivergingBlockBehavior { /// This is the current stable behavior: /// /// ```rust @@ -1556,7 +1556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_struct_path( + pub(crate) fn check_struct_path( &self, qpath: &QPath<'tcx>, hir_id: HirId, @@ -1622,7 +1622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_decl_initializer( + fn check_decl_initializer( &self, hir_id: HirId, pat: &'tcx hir::Pat<'tcx>, @@ -1700,7 +1700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Type check a `let` statement. - pub fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { + fn check_decl_local(&self, local: &'tcx hir::LetStmt<'tcx>) { self.check_decl(local.into()); if local.pat.is_never_pattern() { self.diverges.set(Diverges::Always { @@ -1710,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { + fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, @@ -1745,7 +1745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.diverges.set(self.diverges.get() | old_diverges); } - pub fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { + pub(crate) fn check_block_no_value(&self, blk: &'tcx hir::Block<'tcx>) { let unit = self.tcx.types.unit; let ty = self.check_block_with_expected(blk, ExpectHasType(unit)); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 33f80dd3773..8e69a075030 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -117,7 +117,7 @@ pub(crate) struct FnCtxt<'a, 'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn new( + pub(crate) fn new( root_ctxt: &'a TypeckRootCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, @@ -148,15 +148,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.root_ctxt.infcx.dcx() } - pub fn cause(&self, span: Span, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { + pub(crate) fn cause( + &self, + span: Span, + code: ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx> { ObligationCause::new(span, self.body_id, code) } - pub fn misc(&self, span: Span) -> ObligationCause<'tcx> { + pub(crate) fn misc(&self, span: Span) -> ObligationCause<'tcx> { self.cause(span, ObligationCauseCode::Misc) } - pub fn sess(&self) -> &Session { + pub(crate) fn sess(&self) -> &Session { self.tcx.sess } @@ -165,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Use [`InferCtxtErrorExt::err_ctxt`] to start one without a `TypeckResults`. /// /// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt - pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { + pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> { let mut sub_relations = SubRelations::default(); sub_relations.add_constraints( self, @@ -365,7 +369,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { /// This is a bridge between the interface of HIR ty lowering, which outputs a raw /// `Ty`, and the API in this module, which expect `Ty` to be fully normalized. #[derive(Clone, Copy, Debug)] -pub struct LoweredTy<'tcx> { +pub(crate) struct LoweredTy<'tcx> { /// The unnormalized type provided by the user. pub raw: Ty<'tcx>, @@ -374,7 +378,7 @@ pub struct LoweredTy<'tcx> { } impl<'tcx> LoweredTy<'tcx> { - pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> { + fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> { // FIXME(-Znext-solver): We're still figuring out how to best handle // normalization and this doesn't feel too great. We should look at this // code again before stabilizing it. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 703273968c5..031aa6159d2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - Points out the method's return type as the reason for the expected type. /// - Possible missing semicolon. /// - Possible missing return type if the return type is the default, and not `fn main()`. - pub fn suggest_mismatched_types_on_tail( + pub(crate) fn suggest_mismatched_types_on_tail( &self, err: &mut Diag<'_>, expr: &'tcx hir::Expr<'tcx>, @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.err_ctxt().extract_callable_info(self.body_id, self.param_env, ty) } - pub fn suggest_two_fn_call( + pub(crate) fn suggest_two_fn_call( &self, err: &mut Diag<'_>, lhs_expr: &'tcx hir::Expr<'tcx>, @@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn suggest_remove_last_method_call( + pub(crate) fn suggest_remove_last_method_call( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -280,7 +280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - pub fn suggest_deref_ref_or_into( + pub(crate) fn suggest_deref_ref_or_into( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -747,7 +747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// If the expression is the expression of a closure without block (`|| expr`), a /// block is needed to be added too (`|| { expr; }`). This is denoted by `needs_block`. - pub fn suggest_missing_semicolon( + pub(crate) fn suggest_missing_semicolon( &self, err: &mut Diag<'_>, expression: &'tcx hir::Expr<'tcx>, @@ -2077,7 +2077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the expr is a while or for loop and is the tail expr of its // enclosing body suggest returning a value right after it - pub fn suggest_returning_value_after_loop( + pub(crate) fn suggest_returning_value_after_loop( &self, err: &mut Diag<'_>, expr: &hir::Expr<'tcx>, @@ -2975,7 +2975,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suffix_suggestion = sugg.clone(); suffix_suggestion.push(( if matches!( - (&expected_ty.kind(), &checked_ty.kind()), + (expected_ty.kind(), checked_ty.kind()), (ty::Int(_) | ty::Uint(_), ty::Float(_)) ) { // Remove fractional part from literal, for example `42.0f32` into `42` @@ -3077,7 +3077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); }; - match (&expected_ty.kind(), &checked_ty.kind()) { + match (expected_ty.kind(), checked_ty.kind()) { (ty::Int(exp), ty::Int(found)) => { let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width()) { diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a9c929e76d5..62aa29e673d 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -38,7 +38,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { + pub(crate) fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) { let tcx = self.tcx; let dl = &tcx.data_layout; let span = tcx.hir().span(hir_id); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9ec101196a4..8e6484f1e29 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -8,6 +8,7 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] @@ -87,14 +88,17 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef &tcx.typeck(def_id).used_trait_imports } -fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { +fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); typeck_with_fallback(tcx, def_id, fallback, None) } /// Used only to get `TypeckResults` for type inference during error recovery. /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors. -fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { +fn diagnostic_only_typeck<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> &'tcx ty::TypeckResults<'tcx> { let fallback = move || { let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e0c0adac076..2c3cfcf3cbd 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -42,13 +42,13 @@ impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { } #[derive(Debug)] -pub struct ConfirmResult<'tcx> { +pub(crate) struct ConfirmResult<'tcx> { pub callee: MethodCallee<'tcx>, pub illegal_sized_bound: Option<Span>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn confirm_method( + pub(crate) fn confirm_method( &self, span: Span, self_expr: &'tcx hir::Expr<'tcx>, @@ -66,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { confirm_cx.confirm(unadjusted_self_ty, pick, segment) } - pub fn confirm_method_for_diagnostic( + pub(crate) fn confirm_method_for_diagnostic( &self, span: Span, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index d6110ab94c1..39307a29dad 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -4,7 +4,7 @@ mod confirm; mod prelude_edition_lints; -pub mod probe; +pub(crate) mod probe; mod suggest; use rustc_errors::{Applicability, Diag, SubdiagMessage}; @@ -24,15 +24,15 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, NormalizeExt}; use self::probe::{IsSuggestion, ProbeScope}; -pub use self::MethodError::*; +pub(crate) use self::MethodError::*; use crate::FnCtxt; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { probe::provide(providers); } #[derive(Clone, Copy, Debug)] -pub struct MethodCallee<'tcx> { +pub(crate) struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, pub args: GenericArgsRef<'tcx>, @@ -44,7 +44,7 @@ pub struct MethodCallee<'tcx> { } #[derive(Debug)] -pub enum MethodError<'tcx> { +pub(crate) enum MethodError<'tcx> { // Did not find an applicable method, but we did find various near-misses that may work. NoMatch(NoMatchData<'tcx>), @@ -70,7 +70,7 @@ pub enum MethodError<'tcx> { // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which // could lead to matches if satisfied, and a list of not-in-scope traits which may work. #[derive(Debug)] -pub struct NoMatchData<'tcx> { +pub(crate) struct NoMatchData<'tcx> { pub static_candidates: Vec<CandidateSource>, pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>, @@ -82,7 +82,7 @@ pub struct NoMatchData<'tcx> { // A pared down enum describing just the places from which a method // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum CandidateSource { +pub(crate) enum CandidateSource { Impl(DefId), Trait(DefId /* trait id */), } @@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(result.callee) } - pub fn lookup_method_for_diagnostic( + pub(crate) fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, segment: &hir::PathSegment<'tcx>, @@ -296,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(pick) } - pub fn lookup_probe_for_diagnostic( + pub(crate) fn lookup_probe_for_diagnostic( &self, method_name: Ident, self_ty: Ty<'tcx>, @@ -569,7 +569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Finds item with name `item_name` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - pub fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option<ty::AssocItem> { + fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option<ty::AssocItem> { self.tcx .associated_items(def_id) .find_by_name_and_namespace(self.tcx, item_name, Namespace::ValueNS, def_id) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28f537c87c4..48e33c81b85 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -38,14 +38,14 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; use smallvec::{smallvec, SmallVec}; use self::CandidateKind::*; -pub use self::PickKind::*; +pub(crate) use self::PickKind::*; use super::{suggest, CandidateSource, MethodError, NoMatchData}; use crate::FnCtxt; /// Boolean flag used to indicate if this search is for a suggestion /// or not. If true, we can allow ambiguity and so forth. #[derive(Clone, Copy, Debug)] -pub struct IsSuggestion(pub bool); +pub(crate) struct IsSuggestion(pub bool); pub(crate) struct ProbeContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -134,7 +134,7 @@ enum ProbeResult { /// (at most) one of these. Either the receiver has type `T` and we convert it to `&T` (or with /// `mut`), or it has type `*mut T` and we convert it to `*const T`. #[derive(Debug, PartialEq, Copy, Clone)] -pub enum AutorefOrPtrAdjustment { +pub(crate) enum AutorefOrPtrAdjustment { /// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it. /// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing. Autoref { @@ -158,7 +158,7 @@ impl AutorefOrPtrAdjustment { } #[derive(Debug, Clone)] -pub struct Pick<'tcx> { +pub(crate) struct Pick<'tcx> { pub item: ty::AssocItem, pub kind: PickKind<'tcx>, pub import_ids: SmallVec<[LocalDefId; 1]>, @@ -179,7 +179,7 @@ pub struct Pick<'tcx> { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum PickKind<'tcx> { +pub(crate) enum PickKind<'tcx> { InherentImplPick, ObjectPick, TraitPick, @@ -189,10 +189,10 @@ pub enum PickKind<'tcx> { ), } -pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>; +pub(crate) type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum Mode { +pub(crate) enum Mode { // An expression of the form `receiver.method_name(...)`. // Autoderefs are performed on `receiver`, lookup is done based on the // `self` argument of the method, and static methods aren't considered. @@ -204,7 +204,7 @@ pub enum Mode { } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum ProbeScope { +pub(crate) enum ProbeScope { // Single candidate coming from pre-resolved delegation method. Single(DefId), @@ -507,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.method_autoderef_steps = method_autoderef_steps; } @@ -1288,7 +1288,7 @@ impl<'tcx> Pick<'tcx> { /// Checks whether two picks do not refer to the same trait item for the same `Self` type. /// Only useful for comparisons of picks in order to improve diagnostics. /// Do not use for type checking. - pub fn differs_from(&self, other: &Self) -> bool { + pub(crate) fn differs_from(&self, other: &Self) -> bool { let Self { item: AssocItem { @@ -1312,7 +1312,7 @@ impl<'tcx> Pick<'tcx> { } /// In case there were unstable name collisions, emit them as a lint. - pub fn maybe_emit_unstable_name_collision_hint( + pub(crate) fn maybe_emit_unstable_name_collision_hint( &self, tcx: TyCtxt<'tcx>, span: Span, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3df32dd8505..b78bb8cb98d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -415,7 +415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err } - pub fn suggest_use_shadowed_binding_with_method( + fn suggest_use_shadowed_binding_with_method( &self, self_source: SelfSource<'tcx>, method_name: Ident, @@ -1012,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); - match &self_ty.kind() { + match self_ty.kind() { // Point at the type that couldn't satisfy the bound. ty::Adt(def, _) => { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) @@ -3498,7 +3498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, pick.item.def_id, rcvr.hir_id, - *rcvr_ty, + Some(*rcvr_ty), ); if pick.autoderefs == 0 && !trait_in_other_version_found { err.span_label( @@ -3689,8 +3689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::QPath(ty) = source && !valid_out_of_scope_traits.is_empty() && let hir::TyKind::Path(path) = ty.kind - && let hir::QPath::Resolved(_, path) = path - && let Some(def_id) = path.res.opt_def_id() + && let hir::QPath::Resolved(..) = path && let Some(assoc) = self .tcx .associated_items(valid_out_of_scope_traits[0]) @@ -3700,7 +3699,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // See if the `Type::function(val)` where `function` wasn't found corresponds to a // `Trait` that is imported directly, but `Type` came from a different version of the // same crate. - let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity(); + + let rcvr_ty = self.node_ty_opt(ty.hir_id); trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions( err, assoc.def_id, @@ -4080,7 +4080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut Diag<'_>, item_def_id: DefId, hir_id: hir::HirId, - rcvr_ty: Ty<'_>, + rcvr_ty: Option<Ty<'_>>, ) -> bool { let hir_id = self.tcx.parent_hir_id(hir_id); let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false }; @@ -4110,8 +4110,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut multi_span: MultiSpan = trait_span.into(); multi_span.push_span_label(trait_span, format!("this is the trait that is needed")); let descr = self.tcx.associated_item(item_def_id).descr(); + let rcvr_ty = + rcvr_ty.map(|t| format!("`{t}`")).unwrap_or_else(|| "the receiver".to_string()); multi_span - .push_span_label(item_span, format!("the {descr} is available for `{rcvr_ty}` here")); + .push_span_label(item_span, format!("the {descr} is available for {rcvr_ty} here")); for (def_id, import_def_id) in candidates { if let Some(import_def_id) = import_def_id { multi_span.push_span_label( @@ -4221,19 +4223,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[derive(Copy, Clone, Debug)] -pub enum SelfSource<'a> { +enum SelfSource<'a> { QPath(&'a hir::Ty<'a>), MethodCall(&'a hir::Expr<'a> /* rcvr */), } #[derive(Copy, Clone, PartialEq, Eq)] -pub struct TraitInfo { +pub(crate) struct TraitInfo { pub def_id: DefId, } /// Retrieves all traits in this crate and any dependent crates, /// and wraps them into `TraitInfo` for custom sorting. -pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> { +pub(crate) fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> { tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c54f6cfd099..fb0d30d5b0e 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -25,7 +25,7 @@ use crate::Expectation; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a <op>= b` - pub fn check_binop_assign( + pub(crate) fn check_binop_assign( &self, expr: &'tcx hir::Expr<'tcx>, op: hir::BinOp, @@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Checks a potentially overloaded binary operator. - pub fn check_binop( + pub(crate) fn check_binop( &self, expr: &'tcx hir::Expr<'tcx>, op: hir::BinOp, @@ -770,7 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_user_unop( + pub(crate) fn check_user_unop( &self, ex: &'tcx hir::Expr<'tcx>, operand_ty: Ty<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c4f74adb420..206de455cd5 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -944,7 +944,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn check_dereferenceable( + fn check_dereferenceable( &self, span: Span, expected: Ty<'tcx>, @@ -1336,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. - let missing_parentheses = match (&expected.kind(), fields, had_err) { + let missing_parentheses = match (expected.kind(), fields, had_err) { // #67037: only do this if we could successfully type-check the expected type against // the tuple struct pattern. Otherwise the args could get out of range on e.g., // `let P() = U;` where `P != U` with `struct P<T>(T);`. diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index ad04b6b8b1d..bb227272584 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -246,7 +246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// always know whether a place needs to be mutable or not in the first pass. /// This happens whether there is an implicit mutable reborrow, e.g. when the type /// is used as the receiver of a method call. - pub fn convert_place_derefs_to_mutable(&self, expr: &hir::Expr<'_>) { + pub(crate) fn convert_place_derefs_to_mutable(&self, expr: &hir::Expr<'_>) { // Gather up expressions we want to munge. let mut exprs = vec![expr]; diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index f22a13d292e..fb0fe23be65 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -65,7 +65,7 @@ fn record_rvalue_scope( } } -pub fn resolve_rvalue_scopes<'a, 'tcx>( +pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, scope_tree: &'a ScopeTree, def_id: DefId, diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index a43164589b5..e6b8da3e5d6 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -77,7 +77,7 @@ impl<'tcx> Deref for TypeckRootCtxt<'tcx> { } impl<'tcx> TypeckRootCtxt<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); @@ -124,7 +124,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { infer_ok.value } - pub fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) { + fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) { let infer_var_info = &mut self.infer_var_info.borrow_mut(); // (*) binder skipped diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 55f002291f0..5350affb3bc 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -74,7 +74,7 @@ enum PlaceAncestryRelation { type InferredCaptureInformation<'tcx> = Vec<(Place<'tcx>, ty::CaptureInfo)>; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) { + pub(crate) fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) { InferBorrowKindVisitor { fcx: self }.visit_body(body); // it's our job to process these. diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 0327a3097ec..0853ed9b05b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -35,7 +35,7 @@ use crate::FnCtxt; // resolve_type_vars_in_body, which creates a new TypeTables which // doesn't contain any inference types. impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - pub fn resolve_type_vars_in_body( + pub(crate) fn resolve_type_vars_in_body( &self, body: &'tcx hir::Body<'tcx>, ) -> &'tcx ty::TypeckResults<'tcx> { diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index de2177ebb6e..2a65101d360 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -99,6 +99,4 @@ incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized -incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err} - incremental_write_new = failed to write {$name} to `{$path}`: {$err} diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index b29ba59c9f3..46f30526d2a 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -55,7 +55,7 @@ use {rustc_ast as ast, rustc_graphviz as dot, rustc_hir as hir}; use crate::errors; #[allow(missing_docs)] -pub fn assert_dep_graph(tcx: TyCtxt<'_>) { +pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.unstable_opts.dump_dep_graph { tcx.dep_graph.with_query(dump_graph); @@ -261,7 +261,7 @@ fn dump_graph(query: &DepGraphQuery) { } #[allow(missing_docs)] -pub struct GraphvizDepGraph(FxIndexSet<DepKind>, Vec<(DepKind, DepKind)>); +struct GraphvizDepGraph(FxIndexSet<DepKind>, Vec<(DepKind, DepKind)>); impl<'a> dot::GraphWalk<'a> for GraphvizDepGraph { type Node = DepKind; diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index b68c149d398..cb21f975878 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -6,7 +6,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(incremental_unrecognized_depnode)] -pub struct UnrecognizedDepNode { +pub(crate) struct UnrecognizedDepNode { #[primary_span] pub span: Span, pub name: Symbol, @@ -14,28 +14,28 @@ pub struct UnrecognizedDepNode { #[derive(Diagnostic)] #[diag(incremental_missing_depnode)] -pub struct MissingDepNode { +pub(crate) struct MissingDepNode { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_missing_if_this_changed)] -pub struct MissingIfThisChanged { +pub(crate) struct MissingIfThisChanged { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_ok)] -pub struct Ok { +pub(crate) struct Ok { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_no_path)] -pub struct NoPath { +pub(crate) struct NoPath { #[primary_span] pub span: Span, pub target: Symbol, @@ -44,7 +44,7 @@ pub struct NoPath { #[derive(Diagnostic)] #[diag(incremental_assertion_auto)] -pub struct AssertionAuto<'a> { +pub(crate) struct AssertionAuto<'a> { #[primary_span] pub span: Span, pub name: &'a str, @@ -53,7 +53,7 @@ pub struct AssertionAuto<'a> { #[derive(Diagnostic)] #[diag(incremental_undefined_clean_dirty_assertions_item)] -pub struct UndefinedCleanDirtyItem { +pub(crate) struct UndefinedCleanDirtyItem { #[primary_span] pub span: Span, pub kind: String, @@ -61,7 +61,7 @@ pub struct UndefinedCleanDirtyItem { #[derive(Diagnostic)] #[diag(incremental_undefined_clean_dirty_assertions)] -pub struct UndefinedCleanDirty { +pub(crate) struct UndefinedCleanDirty { #[primary_span] pub span: Span, pub kind: String, @@ -69,7 +69,7 @@ pub struct UndefinedCleanDirty { #[derive(Diagnostic)] #[diag(incremental_repeated_depnode_label)] -pub struct RepeatedDepNodeLabel<'a> { +pub(crate) struct RepeatedDepNodeLabel<'a> { #[primary_span] pub span: Span, pub label: &'a str, @@ -77,7 +77,7 @@ pub struct RepeatedDepNodeLabel<'a> { #[derive(Diagnostic)] #[diag(incremental_unrecognized_depnode_label)] -pub struct UnrecognizedDepNodeLabel<'a> { +pub(crate) struct UnrecognizedDepNodeLabel<'a> { #[primary_span] pub span: Span, pub label: &'a str, @@ -85,7 +85,7 @@ pub struct UnrecognizedDepNodeLabel<'a> { #[derive(Diagnostic)] #[diag(incremental_not_dirty)] -pub struct NotDirty<'a> { +pub(crate) struct NotDirty<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -93,7 +93,7 @@ pub struct NotDirty<'a> { #[derive(Diagnostic)] #[diag(incremental_not_clean)] -pub struct NotClean<'a> { +pub(crate) struct NotClean<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -101,7 +101,7 @@ pub struct NotClean<'a> { #[derive(Diagnostic)] #[diag(incremental_not_loaded)] -pub struct NotLoaded<'a> { +pub(crate) struct NotLoaded<'a> { #[primary_span] pub span: Span, pub dep_node_str: &'a str, @@ -109,7 +109,7 @@ pub struct NotLoaded<'a> { #[derive(Diagnostic)] #[diag(incremental_unknown_item)] -pub struct UnknownItem { +pub(crate) struct UnknownItem { #[primary_span] pub span: Span, pub name: Symbol, @@ -117,14 +117,14 @@ pub struct UnknownItem { #[derive(Diagnostic)] #[diag(incremental_no_cfg)] -pub struct NoCfg { +pub(crate) struct NoCfg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_associated_value_expected_for)] -pub struct AssociatedValueExpectedFor { +pub(crate) struct AssociatedValueExpectedFor { #[primary_span] pub span: Span, pub ident: Ident, @@ -132,21 +132,21 @@ pub struct AssociatedValueExpectedFor { #[derive(Diagnostic)] #[diag(incremental_associated_value_expected)] -pub struct AssociatedValueExpected { +pub(crate) struct AssociatedValueExpected { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_unchecked_clean)] -pub struct UncheckedClean { +pub(crate) struct UncheckedClean { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(incremental_delete_old)] -pub struct DeleteOld<'a> { +pub(crate) struct DeleteOld<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -154,7 +154,7 @@ pub struct DeleteOld<'a> { #[derive(Diagnostic)] #[diag(incremental_create_new)] -pub struct CreateNew<'a> { +pub(crate) struct CreateNew<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -162,7 +162,7 @@ pub struct CreateNew<'a> { #[derive(Diagnostic)] #[diag(incremental_write_new)] -pub struct WriteNew<'a> { +pub(crate) struct WriteNew<'a> { pub name: &'a str, pub path: PathBuf, pub err: std::io::Error, @@ -170,14 +170,14 @@ pub struct WriteNew<'a> { #[derive(Diagnostic)] #[diag(incremental_canonicalize_path)] -pub struct CanonicalizePath { +pub(crate) struct CanonicalizePath { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_create_incr_comp_dir)] -pub struct CreateIncrCompDir<'a> { +pub(crate) struct CreateIncrCompDir<'a> { pub tag: &'a str, pub path: &'a Path, pub err: std::io::Error, @@ -185,7 +185,7 @@ pub struct CreateIncrCompDir<'a> { #[derive(Diagnostic)] #[diag(incremental_create_lock)] -pub struct CreateLock<'a> { +pub(crate) struct CreateLock<'a> { pub lock_err: std::io::Error, pub session_dir: &'a Path, #[note(incremental_lock_unsupported)] @@ -197,91 +197,84 @@ pub struct CreateLock<'a> { #[derive(Diagnostic)] #[diag(incremental_delete_lock)] -pub struct DeleteLock<'a> { +pub(crate) struct DeleteLock<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_hard_link_failed)] -pub struct HardLinkFailed<'a> { +pub(crate) struct HardLinkFailed<'a> { pub path: &'a Path, } #[derive(Diagnostic)] #[diag(incremental_delete_partial)] -pub struct DeletePartial<'a> { +pub(crate) struct DeletePartial<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_delete_full)] -pub struct DeleteFull<'a> { +pub(crate) struct DeleteFull<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_finalize)] -pub struct Finalize<'a> { +pub(crate) struct Finalize<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_invalid_gc_failed)] -pub struct InvalidGcFailed<'a> { +pub(crate) struct InvalidGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_finalized_gc_failed)] -pub struct FinalizedGcFailed<'a> { +pub(crate) struct FinalizedGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_session_gc_failed)] -pub struct SessionGcFailed<'a> { +pub(crate) struct SessionGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_assert_not_loaded)] -pub struct AssertNotLoaded; +pub(crate) struct AssertNotLoaded; #[derive(Diagnostic)] #[diag(incremental_assert_loaded)] -pub struct AssertLoaded; +pub(crate) struct AssertLoaded; #[derive(Diagnostic)] #[diag(incremental_delete_incompatible)] -pub struct DeleteIncompatible { +pub(crate) struct DeleteIncompatible { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_load_dep_graph)] -pub struct LoadDepGraph { +pub(crate) struct LoadDepGraph { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_write_dep_graph)] -pub struct WriteDepGraph<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - -#[derive(Diagnostic)] #[diag(incremental_move_dep_graph)] -pub struct MoveDepGraph<'a> { +pub(crate) struct MoveDepGraph<'a> { pub from: &'a Path, pub to: &'a Path, pub err: std::io::Error, @@ -289,14 +282,14 @@ pub struct MoveDepGraph<'a> { #[derive(Diagnostic)] #[diag(incremental_create_dep_graph)] -pub struct CreateDepGraph<'a> { +pub(crate) struct CreateDepGraph<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_copy_workproduct_to_cache)] -pub struct CopyWorkProductToCache<'a> { +pub(crate) struct CopyWorkProductToCache<'a> { pub from: &'a Path, pub to: &'a Path, pub err: std::io::Error, @@ -304,13 +297,13 @@ pub struct CopyWorkProductToCache<'a> { #[derive(Diagnostic)] #[diag(incremental_delete_workproduct)] -pub struct DeleteWorkProduct<'a> { +pub(crate) struct DeleteWorkProduct<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] #[diag(incremental_corrupt_file)] -pub struct CorruptFile<'a> { +pub(crate) struct CorruptFile<'a> { pub path: &'a Path, } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index fcdcb08eed6..c79d108183c 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod assert_dep_graph; diff --git a/compiler/rustc_incremental/src/persist/data.rs b/compiler/rustc_incremental/src/persist/data.rs index 81e5410978d..d962dc866f4 100644 --- a/compiler/rustc_incremental/src/persist/data.rs +++ b/compiler/rustc_incremental/src/persist/data.rs @@ -4,7 +4,7 @@ use rustc_macros::{Decodable, Encodable}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; #[derive(Debug, Encodable, Decodable)] -pub struct SerializedWorkProduct { +pub(crate) struct SerializedWorkProduct { /// node that produced the work-product pub id: WorkProductId, diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 1e02324f404..88cb82f0f37 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -133,7 +133,7 @@ struct Assertion { loaded_from_disk: Labels, } -pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { +pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { if !tcx.sess.opts.unstable_opts.query_dep_graph { return; } @@ -174,7 +174,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { }) } -pub struct DirtyCleanVisitor<'tcx> { +struct DirtyCleanVisitor<'tcx> { tcx: TyCtxt<'tcx>, checked_attrs: FxHashSet<ast::AttrId>, } @@ -429,7 +429,7 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { /// A visitor that collects all `#[rustc_clean]` attributes from /// the HIR. It is used to verify that we really ran checks for all annotated /// nodes. -pub struct FindAllAttrs<'tcx> { +struct FindAllAttrs<'tcx> { tcx: TyCtxt<'tcx>, found_attrs: Vec<&'tcx Attribute>, } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 174414d0c85..f834c48cbf8 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -89,7 +89,7 @@ where /// incompatible version of the compiler. /// - Returns `Err(..)` if some kind of IO error occurred while reading the /// file. -pub fn read_file( +pub(crate) fn read_file( path: &Path, report_incremental_info: bool, is_nightly_build: bool, diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 0e87bc1e692..feb25a9a89d 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -157,7 +157,7 @@ pub(crate) fn work_products_path(sess: &Session) -> PathBuf { } /// Returns the path to a session's query cache. -pub fn query_cache_path(sess: &Session) -> PathBuf { +pub(crate) fn query_cache_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME) } diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index b5e4f02a8d1..eb47ac3c68e 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -2,6 +2,8 @@ #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(extend_one, new_uninit, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod bit_set; diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 1a5c0137219..76ea9c3433d 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -3,7 +3,7 @@ use rustc_span::Span; #[derive(Diagnostic)] #[diag(infer_opaque_hidden_type)] -pub struct OpaqueHiddenTypeDiag { +pub(crate) struct OpaqueHiddenTypeDiag { #[primary_span] #[label] pub span: Span, diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index f35a8162d96..95888beb6b1 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -167,7 +167,7 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { } fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) { - self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP), sub, sup) + self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup) } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) { diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 0dde3082d48..9a5674369da 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -18,11 +18,11 @@ pub(crate) struct RegionRelations<'a, 'tcx> { } impl<'a, 'tcx> RegionRelations<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, free_regions: &'a FreeRegionMap<'tcx>) -> Self { Self { tcx, free_regions } } - pub fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { + pub(crate) fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> { self.free_regions.lub_param_regions(self.tcx, r_a, r_b) } } @@ -80,7 +80,7 @@ impl<'tcx> FreeRegionMap<'tcx> { /// cases, this is more conservative than necessary, in order to /// avoid making arbitrary choices. See /// `TransitiveRelation::postdom_upper_bound` for more details. - pub fn lub_param_regions( + pub(crate) fn lub_param_regions( &self, tcx: TyCtxt<'tcx>, r_a: Region<'tcx>, diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index c2c0c7a41fe..e5533213400 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -43,7 +43,7 @@ pub(crate) fn resolve<'tcx>( /// Contains the result of lexical region resolution. Offers methods /// to lookup up the final value of a region variable. #[derive(Clone)] -pub struct LexicalRegionResolutions<'tcx> { +pub(crate) struct LexicalRegionResolutions<'tcx> { pub(crate) values: IndexVec<RegionVid, VarValue<'tcx>>, } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f2fc25a2d2e..5aa7f259685 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -390,7 +390,7 @@ pub enum SubregionOrigin<'tcx> { /// The given region parameter was instantiated with a region /// that must outlive some other region. - RelateRegionParamBound(Span), + RelateRegionParamBound(Span, Option<Ty<'tcx>>), /// Creating a pointer `b` to contents of another reference. Reborrow(Span), @@ -859,7 +859,7 @@ impl<'tcx> InferCtxt<'tcx> { ) { self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { let origin = SubregionOrigin::from_obligation_cause(cause, || { - RelateRegionParamBound(cause.span) + RelateRegionParamBound(cause.span, None) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` }) @@ -1685,7 +1685,7 @@ impl<'tcx> SubregionOrigin<'tcx> { Subtype(ref a) => a.span(), RelateObjectBound(a) => a, RelateParamBound(a, ..) => a, - RelateRegionParamBound(a) => a, + RelateRegionParamBound(a, _) => a, Reborrow(a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span, @@ -1726,6 +1726,10 @@ impl<'tcx> SubregionOrigin<'tcx> { SubregionOrigin::AscribeUserTypeProvePredicate(span) } + traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => { + SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty)) + } + _ => default(), } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 542104fa10b..6fa10a95313 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -705,7 +705,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> { /// not only the generalized type, but also a bool flag /// indicating whether further WF checks are needed. #[derive(Debug)] -pub struct Generalization<T> { +struct Generalization<T> { /// When generalizing `<?0 as Trait>::Assoc` or /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc` /// for `?0` generalization returns an inference diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index f555fedbb5b..1eafbb9acb3 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -29,7 +29,7 @@ use crate::traits::ObligationCause; /// /// GLB moves "down" the lattice (to smaller values); LUB moves /// "up" the lattice (to bigger values). -pub trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation<InferCtxt<'tcx>> { +pub(crate) trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation<InferCtxt<'tcx>> { fn infcx(&self) -> &'f InferCtxt<'tcx>; fn cause(&self) -> &ObligationCause<'tcx>; diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index bc954054ea2..fdf55447f79 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -170,7 +170,7 @@ impl<'tcx> InferCtxt<'tcx> { } } -pub struct InferenceFudger<'a, 'tcx> { +struct InferenceFudger<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>), int_vars: Range<IntVid>, diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 50a0d3bf214..366af913ddc 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -158,7 +158,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } impl<'tcx> InferCtxtUndoLogs<'tcx> { - pub fn start_snapshot(&mut self) -> Snapshot<'tcx> { + pub(crate) fn start_snapshot(&mut self) -> Snapshot<'tcx> { self.num_open_snapshots += 1; Snapshot { undo_len: self.logs.len(), _marker: PhantomData } } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 25ac8ba974b..94aa2ddd92f 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -27,9 +27,8 @@ #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(rustdoc_internals)] -#![feature(try_blocks)] -#![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc +#![warn(unreachable_pub)] // tidy-alphabetical-end #[macro_use] diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 4f34c139545..3a05b576a97 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -22,7 +22,7 @@ pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine}; pub(crate) use self::project::UndoLog; pub use self::project::{ MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry, - ProjectionCacheKey, ProjectionCacheStorage, Reveal, + ProjectionCacheKey, ProjectionCacheStorage, }; pub use self::ImplSource::*; pub use self::SelectionError::*; diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 9ed557ec40b..3d4ec9e51db 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -2,7 +2,7 @@ use rustc_data_structures::snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage}; use rustc_data_structures::undo_log::Rollback; -pub use rustc_middle::traits::{EvaluationResult, Reveal}; +use rustc_middle::traits::EvaluationResult; use rustc_middle::ty; use super::PredicateObligation; diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 786e2bb511f..f66b9eb3a28 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -18,11 +18,19 @@ use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { - tls::with_opt(|tcx| { - if let Some(tcx) = tcx { - let _span = tcx.source_span(def_id); - // Sanity check: relative span's parent must be an absolute span. - debug_assert_eq!(_span.data_untracked().parent, None); + tls::with_context_opt(|icx| { + if let Some(icx) = icx { + // `track_span_parent` gets called a lot from HIR lowering code. + // Skip doing anything if we aren't tracking dependencies. + let tracks_deps = match icx.task_deps { + TaskDepsRef::Allow(..) => true, + TaskDepsRef::EvalAlways | TaskDepsRef::Ignore | TaskDepsRef::Forbid => false, + }; + if tracks_deps { + let _span = icx.tcx.source_span(def_id); + // Sanity check: relative span's parent must be an absolute span. + debug_assert_eq!(_span.data_untracked().parent, None); + } } }) } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 3492df69b8d..3b6c2acaf30 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -2,6 +2,7 @@ #![feature(decl_macro)] #![feature(let_chains)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod callbacks; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 96a6f52d60b..779b98d073d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -784,7 +784,20 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { } ); }); + rustc_hir_analysis::check_crate(tcx); + sess.time("MIR_coroutine_by_move_body", || { + tcx.hir().par_body_owners(|def_id| { + if tcx.needs_coroutine_by_move_body_def_id(def_id) { + tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); + } + }); + }); + // Freeze definitions as we don't add new ones at this point. + // We need to wait until now since we synthesize a by-move body + // This improves performance by allowing lock-free access to them. + tcx.untracked().definitions.freeze(); + sess.time("MIR_borrow_checking", || { tcx.hir().par_body_owners(|def_id| { // Run unsafety check because it's responsible for stealing and @@ -816,6 +829,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { ); } }); + sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index c5d56c15c6e..44e07b36b61 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -98,7 +98,7 @@ impl<'tcx> Queries<'tcx> { self.parse.compute(|| passes::parse(&self.compiler.sess)) } - pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { + pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'tcx, &'tcx GlobalCtxt<'tcx>>> { self.gcx.compute(|| { let krate = self.parse()?.steal(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 34f2dca7c42..486136a2bcc 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -774,6 +774,7 @@ fn test_unstable_options_tracking_hash() { tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(embed_source, true); tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 2116ba6c079..31fdd2d7cec 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -23,6 +23,7 @@ // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod cursor; diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 28aef9055ef..08a50050a36 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -361,6 +361,11 @@ lint_improper_ctypes_box = box cannot be represented as a single pointer lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead lint_improper_ctypes_char_reason = the `char` type has no C equivalent + +lint_improper_ctypes_cstr_help = + consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout + lint_improper_ctypes_dyn = trait objects have no C equivalent lint_improper_ctypes_enum_repr_help = diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 85132dd4f98..d8482567bbe 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1925,8 +1925,8 @@ impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( tcx: TyCtxt<'tcx>, inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>, - item: DefId, - lifetime: DefId, + item: LocalDefId, + lifetime: LocalDefId, ) -> Vec<ty::Region<'tcx>> { let item_generics = tcx.generics_of(item); @@ -1934,7 +1934,7 @@ impl ExplicitOutlivesRequirements { .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { ty::ReEarlyParam(ebr) - if item_generics.region_param(ebr, tcx).def_id == lifetime => + if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() => { Some(b) } @@ -1982,7 +1982,7 @@ impl ExplicitOutlivesRequirements { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() - .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id })), + .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })), _ => false, }; @@ -2097,7 +2097,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { inferred_outlives .iter() .filter(|(_, span)| !predicate.span.contains(*span)), - item.owner_id.to_def_id(), + item.owner_id.def_id, region_def_id, ), &predicate.bounds, diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 2060858cc8a..a9de258e005 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -151,10 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Node::Stmt(stmt) = node && let StmtKind::Semi(e) = stmt.kind && e.hir_id == expr.hir_id + && let Some(arg_span) = arg.span.find_ancestor_inside(expr.span) { UseLetUnderscoreIgnoreSuggestion::Suggestion { - start_span: expr.span.shrink_to_lo().until(arg.span), - end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + start_span: expr.span.shrink_to_lo().until(arg_span), + end_span: arg_span.shrink_to_hi().until(expr.span.shrink_to_hi()), } } else { UseLetUnderscoreIgnoreSuggestion::Note diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 6fb0a624644..0ee9dda1fef 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -413,7 +413,7 @@ pub fn check_ast_node<'a>( } } -pub fn check_ast_node_inner<'a, T: EarlyLintPass>( +fn check_ast_node_inner<'a, T: EarlyLintPass>( sess: &Session, check_node: impl EarlyCheckNode<'a>, context: EarlyContext<'_>, diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 85ee18aba8f..d109a5c9030 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -8,7 +8,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(lint_overruled_attribute, code = E0453)] -pub struct OverruledAttribute<'a> { +pub(crate) struct OverruledAttribute<'a> { #[primary_span] pub span: Span, #[label] @@ -19,7 +19,7 @@ pub struct OverruledAttribute<'a> { pub sub: OverruledAttributeSub, } -pub enum OverruledAttributeSub { +pub(crate) enum OverruledAttributeSub { DefaultSource { id: String }, NodeSource { span: Span, reason: Option<Symbol> }, CommandLineSource, @@ -52,7 +52,7 @@ impl Subdiagnostic for OverruledAttributeSub { #[derive(Diagnostic)] #[diag(lint_malformed_attribute, code = E0452)] -pub struct MalformedAttribute { +pub(crate) struct MalformedAttribute { #[primary_span] pub span: Span, #[subdiagnostic] @@ -60,7 +60,7 @@ pub struct MalformedAttribute { } #[derive(Subdiagnostic)] -pub enum MalformedAttributeSub { +pub(crate) enum MalformedAttributeSub { #[label(lint_bad_attribute_argument)] BadAttributeArgument(#[primary_span] Span), #[label(lint_reason_must_be_string_literal)] @@ -71,7 +71,7 @@ pub enum MalformedAttributeSub { #[derive(Diagnostic)] #[diag(lint_unknown_tool_in_scoped_lint, code = E0710)] -pub struct UnknownToolInScopedLint { +pub(crate) struct UnknownToolInScopedLint { #[primary_span] pub span: Option<Span>, pub tool_name: Symbol, @@ -82,7 +82,7 @@ pub struct UnknownToolInScopedLint { #[derive(Diagnostic)] #[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)] -pub struct BuiltinEllipsisInclusiveRangePatterns { +pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { #[primary_span] pub span: Span, #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] @@ -92,20 +92,20 @@ pub struct BuiltinEllipsisInclusiveRangePatterns { #[derive(Subdiagnostic)] #[note(lint_requested_level)] -pub struct RequestedLevel<'a> { +pub(crate) struct RequestedLevel<'a> { pub level: Level, pub lint_name: &'a str, } #[derive(Diagnostic)] #[diag(lint_unsupported_group, code = E0602)] -pub struct UnsupportedGroup { +pub(crate) struct UnsupportedGroup { pub lint_group: String, } #[derive(Diagnostic)] #[diag(lint_check_name_unknown_tool, code = E0602)] -pub struct CheckNameUnknownTool<'a> { +pub(crate) struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] pub sub: RequestedLevel<'a>, diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 990fb2d16f9..8824e1dfe50 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -10,7 +10,9 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::edition::Edition; use rustc_span::Span; use crate::{fluent_generated as fluent, LateContext, LateLintPass}; @@ -54,10 +56,10 @@ declare_lint! { pub IMPL_TRAIT_OVERCAPTURES, Allow, "`impl Trait` will capture more lifetimes than possibly intended in edition 2024", - //@future_incompatible = FutureIncompatibleInfo { - // reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), - // reference: "<FIXME>", - //}; + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>", + }; } declare_lint! { @@ -300,16 +302,17 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> { Some( ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id), ) => { - if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy { + if self.tcx.def_kind(self.tcx.local_parent(def_id)) == DefKind::OpaqueTy + { let def_id = self .tcx - .map_opaque_lifetime_to_parent_lifetime(def_id.expect_local()) + .map_opaque_lifetime_to_parent_lifetime(def_id) .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id()) .expect("variable should have been duplicated from parent"); explicitly_captured.insert(def_id); } else { - explicitly_captured.insert(def_id); + explicitly_captured.insert(def_id.to_def_id()); } } _ => { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 044c9413f0b..65571815019 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -8,7 +8,7 @@ use rustc_hir::{ BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind, Path, PathSegment, QPath, Ty, TyKind, }; -use rustc_middle::ty::{self, Ty as MiddleTy}; +use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -415,14 +415,17 @@ declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE impl LateLintPass<'_> for Diagnostics { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + let collect_args_tys_and_spans = |args: &[Expr<'_>], reserve_one_extra: bool| { + let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra)); + result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span))); + result + }; // Only check function calls and method calls. - let (span, def_id, fn_gen_args, call_tys) = match expr.kind { + let (span, def_id, fn_gen_args, arg_tys_and_spans) = match expr.kind { ExprKind::Call(callee, args) => { match cx.typeck_results().node_type(callee.hir_id).kind() { &ty::FnDef(def_id, fn_gen_args) => { - let call_tys: Vec<_> = - args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); - (callee.span, def_id, fn_gen_args, call_tys) + (callee.span, def_id, fn_gen_args, collect_args_tys_and_spans(args, false)) } _ => return, // occurs for fns passed as args } @@ -432,38 +435,40 @@ impl LateLintPass<'_> for Diagnostics { else { return; }; - let mut call_tys: Vec<_> = - args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect(); - call_tys.insert(0, cx.tcx.types.self_param); // dummy inserted for `self` - (span, def_id, fn_gen_args, call_tys) + let mut args = collect_args_tys_and_spans(args, true); + args.insert(0, (cx.tcx.types.self_param, _recv.span)); // dummy inserted for `self` + (span, def_id, fn_gen_args, args) } _ => return, }; - // Is the callee marked with `#[rustc_lint_diagnostics]`? - let has_attr = ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args) - .ok() - .flatten() - .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics)); - - // Closure: is the type `{D,Subd}iagMessage`? - let is_diag_message = |ty: MiddleTy<'_>| { - if let Some(adt_def) = ty.ty_adt_def() - && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) - && matches!(name, sym::DiagMessage | sym::SubdiagMessage) - { - true - } else { - false - } - }; + Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args); + Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans); + } +} - // Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters? - let mut impl_into_diagnostic_message_params = vec![]; +impl Diagnostics { + // Is the type `{D,Subd}iagMessage`? + fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: MiddleTy<'cx>) -> bool { + if let Some(adt_def) = ty.ty_adt_def() + && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did()) + && matches!(name, sym::DiagMessage | sym::SubdiagMessage) + { + true + } else { + false + } + } + + fn untranslatable_diagnostic<'cx>( + cx: &LateContext<'cx>, + def_id: DefId, + arg_tys_and_spans: &[(MiddleTy<'cx>, Span)], + ) { let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder(); let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates; for (i, ¶m_ty) in fn_sig.inputs().iter().enumerate() { - if let ty::Param(p) = param_ty.kind() { + if let ty::Param(sig_param) = param_ty.kind() { // It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`. for pred in predicates.iter() { if let Some(trait_pred) = pred.as_trait_clause() @@ -471,27 +476,53 @@ impl LateLintPass<'_> for Diagnostics { && trait_ref.self_ty() == param_ty // correct predicate for the param? && cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id) && let ty1 = trait_ref.args.type_at(1) - && is_diag_message(ty1) + && Self::is_diag_message(cx, ty1) { - impl_into_diagnostic_message_params.push((i, p.name)); + // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg + // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an + // `UNTRANSLATABLE_DIAGNOSTIC` lint. + let (arg_ty, arg_span) = arg_tys_and_spans[i]; + + // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? + let is_translatable = Self::is_diag_message(cx, arg_ty) + || matches!(arg_ty.kind(), ty::Param(arg_param) if arg_param.name == sig_param.name); + if !is_translatable { + cx.emit_span_lint( + UNTRANSLATABLE_DIAGNOSTIC, + arg_span, + UntranslatableDiag, + ); + } } } } } + } - // Is the callee interesting? - if !has_attr && impl_into_diagnostic_message_params.is_empty() { + fn diagnostic_outside_of_impl<'cx>( + cx: &LateContext<'cx>, + span: Span, + current_id: HirId, + def_id: DefId, + fn_gen_args: GenericArgsRef<'cx>, + ) { + // Is the callee marked with `#[rustc_lint_diagnostics]`? + let Some(inst) = + ty::Instance::try_resolve(cx.tcx, cx.param_env, def_id, fn_gen_args).ok().flatten() + else { return; - } + }; + let has_attr = cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics); + if !has_attr { + return; + }; - // Is the parent method marked with `#[rustc_lint_diagnostics]`? - let mut parent_has_attr = false; - for (hir_id, _parent) in cx.tcx.hir().parent_iter(expr.hir_id) { + for (hir_id, _parent) in cx.tcx.hir().parent_iter(current_id) { if let Some(owner_did) = hir_id.as_owner() && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics) { - parent_has_attr = true; - break; + // The parent method is marked with `#[rustc_lint_diagnostics]` + return; } } @@ -500,37 +531,22 @@ impl LateLintPass<'_> for Diagnostics { // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`. // // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint. - if has_attr && !parent_has_attr { - let mut is_inside_appropriate_impl = false; - for (_hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) { - debug!(?parent); - if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent - && let Impl { of_trait: Some(of_trait), .. } = impl_ - && let Some(def_id) = of_trait.trait_def_id() - && let Some(name) = cx.tcx.get_diagnostic_name(def_id) - && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) - { - is_inside_appropriate_impl = true; - break; - } - } - debug!(?is_inside_appropriate_impl); - if !is_inside_appropriate_impl { - cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); + let mut is_inside_appropriate_impl = false; + for (_hir_id, parent) in cx.tcx.hir().parent_iter(current_id) { + debug!(?parent); + if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent + && let Impl { of_trait: Some(of_trait), .. } = impl_ + && let Some(def_id) = of_trait.trait_def_id() + && let Some(name) = cx.tcx.get_diagnostic_name(def_id) + && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) + { + is_inside_appropriate_impl = true; + break; } } - - // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg - // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an - // `UNTRANSLATABLE_DIAGNOSTIC` lint. - for (param_i, param_i_p_name) in impl_into_diagnostic_message_params { - // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`? - let arg_ty = call_tys[param_i]; - let is_translatable = is_diag_message(arg_ty) - || matches!(arg_ty.kind(), ty::Param(p) if p.name == param_i_p_name); - if !is_translatable { - cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag); - } + debug!(?is_inside_appropriate_impl); + if !is_inside_appropriate_impl { + cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl); } } } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 638b623510e..cb369d99a84 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -47,7 +47,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ /// Implements the AST traversal for late lint passes. `T` provides the /// `check_*` methods. -pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { +struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { context: LateContext<'tcx>, pass: T, } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 91d4f95df80..07ac63ec96c 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1103,7 +1103,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; } -pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) { +pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) { match lint_name.split_once("::") { Some((tool_name, lint_name)) => { let tool_name = Symbol::intern(tool_name); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1828b6ea93c..c5a5c5b30af 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -39,6 +39,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(trait_upcasting)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod async_closures; @@ -572,7 +573,8 @@ fn register_builtins(store: &mut LintStore) { "byte_slice_in_packed_struct_with_derive", "converted into hard error, see issue #107457 \ <https://github.com/rust-lang/rust/issues/107457> for more information", - ) + ); + store.register_removed("writes_through_immutable_pointer", "converted into hard error"); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c12c5427997..c6bcb1f3e83 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -26,7 +26,7 @@ use crate::{fluent_generated as fluent, LateContext}; // array_into_iter.rs #[derive(LintDiagnostic)] #[diag(lint_shadowed_into_iter)] -pub struct ShadowedIntoIterDiag { +pub(crate) struct ShadowedIntoIterDiag { pub target: &'static str, pub edition: &'static str, #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")] @@ -36,7 +36,7 @@ pub struct ShadowedIntoIterDiag { } #[derive(Subdiagnostic)] -pub enum ShadowedIntoIterDiagSub { +pub(crate) enum ShadowedIntoIterDiagSub { #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] RemoveIntoIter { #[primary_span] @@ -57,7 +57,7 @@ pub enum ShadowedIntoIterDiagSub { // builtin.rs #[derive(LintDiagnostic)] #[diag(lint_builtin_while_true)] -pub struct BuiltinWhileTrue { +pub(crate) struct BuiltinWhileTrue { #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, pub replace: String, @@ -65,7 +65,7 @@ pub struct BuiltinWhileTrue { #[derive(LintDiagnostic)] #[diag(lint_builtin_non_shorthand_field_patterns)] -pub struct BuiltinNonShorthandFieldPatterns { +pub(crate) struct BuiltinNonShorthandFieldPatterns { pub ident: Ident, #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] pub suggestion: Span, @@ -73,7 +73,7 @@ pub struct BuiltinNonShorthandFieldPatterns { } #[derive(LintDiagnostic)] -pub enum BuiltinUnsafe { +pub(crate) enum BuiltinUnsafe { #[diag(lint_builtin_allow_internal_unsafe)] AllowInternalUnsafe, #[diag(lint_builtin_unsafe_block)] @@ -121,16 +121,16 @@ pub enum BuiltinUnsafe { #[derive(LintDiagnostic)] #[diag(lint_builtin_missing_doc)] -pub struct BuiltinMissingDoc<'a> { +pub(crate) struct BuiltinMissingDoc<'a> { pub article: &'a str, pub desc: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_builtin_missing_copy_impl)] -pub struct BuiltinMissingCopyImpl; +pub(crate) struct BuiltinMissingCopyImpl; -pub struct BuiltinMissingDebugImpl<'a> { +pub(crate) struct BuiltinMissingDebugImpl<'a> { pub tcx: TyCtxt<'a>, pub def_id: DefId, } @@ -145,7 +145,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_anonymous_params)] -pub struct BuiltinAnonymousParams<'a> { +pub(crate) struct BuiltinAnonymousParams<'a> { #[suggestion(code = "_: {ty_snip}")] pub suggestion: (Span, Applicability), pub ty_snip: &'a str, @@ -154,7 +154,7 @@ pub struct BuiltinAnonymousParams<'a> { // FIXME(davidtwco) translatable deprecated attr #[derive(LintDiagnostic)] #[diag(lint_builtin_deprecated_attr_link)] -pub struct BuiltinDeprecatedAttrLink<'a> { +pub(crate) struct BuiltinDeprecatedAttrLink<'a> { pub name: Symbol, pub reason: &'a str, pub link: &'a str, @@ -163,7 +163,7 @@ pub struct BuiltinDeprecatedAttrLink<'a> { } #[derive(Subdiagnostic)] -pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { +pub(crate) enum BuiltinDeprecatedAttrLinkSuggestion<'a> { #[suggestion(lint_msg_suggestion, code = "", applicability = "machine-applicable")] Msg { #[primary_span] @@ -179,7 +179,7 @@ pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> { #[derive(LintDiagnostic)] #[diag(lint_builtin_deprecated_attr_used)] -pub struct BuiltinDeprecatedAttrUsed { +pub(crate) struct BuiltinDeprecatedAttrUsed { pub name: String, #[suggestion( lint_builtin_deprecated_attr_default_suggestion, @@ -192,7 +192,7 @@ pub struct BuiltinDeprecatedAttrUsed { #[derive(LintDiagnostic)] #[diag(lint_builtin_unused_doc_comment)] -pub struct BuiltinUnusedDocComment<'a> { +pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, #[label] pub label: Span, @@ -201,7 +201,7 @@ pub struct BuiltinUnusedDocComment<'a> { } #[derive(Subdiagnostic)] -pub enum BuiltinUnusedDocCommentSub { +pub(crate) enum BuiltinUnusedDocCommentSub { #[help(lint_plain_help)] PlainHelp, #[help(lint_block_help)] @@ -210,7 +210,7 @@ pub enum BuiltinUnusedDocCommentSub { #[derive(LintDiagnostic)] #[diag(lint_builtin_no_mangle_generic)] -pub struct BuiltinNoMangleGeneric { +pub(crate) struct BuiltinNoMangleGeneric { // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] @@ -219,21 +219,21 @@ pub struct BuiltinNoMangleGeneric { #[derive(LintDiagnostic)] #[diag(lint_builtin_const_no_mangle)] -pub struct BuiltinConstNoMangle { +pub(crate) struct BuiltinConstNoMangle { #[suggestion(code = "pub static", applicability = "machine-applicable")] pub suggestion: Span, } #[derive(LintDiagnostic)] #[diag(lint_builtin_mutable_transmutes)] -pub struct BuiltinMutablesTransmutes; +pub(crate) struct BuiltinMutablesTransmutes; #[derive(LintDiagnostic)] #[diag(lint_builtin_unstable_features)] -pub struct BuiltinUnstableFeatures; +pub(crate) struct BuiltinUnstableFeatures; // lint_ungated_async_fn_track_caller -pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { +pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { pub label: Span, pub session: &'a Session, } @@ -252,7 +252,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_unreachable_pub)] -pub struct BuiltinUnreachablePub<'a> { +pub(crate) struct BuiltinUnreachablePub<'a> { pub what: &'a str, #[suggestion(code = "pub(crate)")] pub suggestion: (Span, Applicability), @@ -262,12 +262,12 @@ pub struct BuiltinUnreachablePub<'a> { #[derive(LintDiagnostic)] #[diag(lint_macro_expr_fragment_specifier_2024_migration)] -pub struct MacroExprFragment2024 { +pub(crate) struct MacroExprFragment2024 { #[suggestion(code = "expr_2021", applicability = "machine-applicable")] pub suggestion: Span, } -pub struct BuiltinTypeAliasBounds<'a, 'hir> { +pub(crate) struct BuiltinTypeAliasBounds<'a, 'hir> { pub in_where_clause: bool, pub label: Span, pub enable_feat_help: bool, @@ -338,13 +338,13 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_, '_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_trivial_bounds)] -pub struct BuiltinTrivialBounds<'a> { +pub(crate) struct BuiltinTrivialBounds<'a> { pub predicate_kind_name: &'a str, pub predicate: Clause<'a>, } #[derive(LintDiagnostic)] -pub enum BuiltinEllipsisInclusiveRangePatternsLint { +pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] Parenthesise { #[suggestion(code = "{replace}", applicability = "machine-applicable")] @@ -360,7 +360,7 @@ pub enum BuiltinEllipsisInclusiveRangePatternsLint { #[derive(LintDiagnostic)] #[diag(lint_builtin_keyword_idents)] -pub struct BuiltinKeywordIdents { +pub(crate) struct BuiltinKeywordIdents { pub kw: Ident, pub next: Edition, #[suggestion(code = "r#{kw}", applicability = "machine-applicable")] @@ -369,7 +369,7 @@ pub struct BuiltinKeywordIdents { #[derive(LintDiagnostic)] #[diag(lint_builtin_explicit_outlives)] -pub struct BuiltinExplicitOutlives { +pub(crate) struct BuiltinExplicitOutlives { pub count: usize, #[subdiagnostic] pub suggestion: BuiltinExplicitOutlivesSuggestion, @@ -377,7 +377,7 @@ pub struct BuiltinExplicitOutlives { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion)] -pub struct BuiltinExplicitOutlivesSuggestion { +pub(crate) struct BuiltinExplicitOutlivesSuggestion { #[suggestion_part(code = "")] pub spans: Vec<Span>, #[applicability] @@ -386,7 +386,7 @@ pub struct BuiltinExplicitOutlivesSuggestion { #[derive(LintDiagnostic)] #[diag(lint_builtin_incomplete_features)] -pub struct BuiltinIncompleteFeatures { +pub(crate) struct BuiltinIncompleteFeatures { pub name: Symbol, #[subdiagnostic] pub note: Option<BuiltinFeatureIssueNote>, @@ -397,21 +397,21 @@ pub struct BuiltinIncompleteFeatures { #[derive(LintDiagnostic)] #[diag(lint_builtin_internal_features)] #[note] -pub struct BuiltinInternalFeatures { +pub(crate) struct BuiltinInternalFeatures { pub name: Symbol, } #[derive(Subdiagnostic)] #[help(lint_help)] -pub struct BuiltinIncompleteFeaturesHelp; +pub(crate) struct BuiltinIncompleteFeaturesHelp; #[derive(Subdiagnostic)] #[note(lint_note)] -pub struct BuiltinFeatureIssueNote { +pub(crate) struct BuiltinFeatureIssueNote { pub n: NonZero<u32>, } -pub struct BuiltinUnpermittedTypeInit<'a> { +pub(crate) struct BuiltinUnpermittedTypeInit<'a> { pub msg: DiagMessage, pub ty: Ty<'a>, pub label: Span, @@ -436,7 +436,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { } // FIXME(davidtwco): make translatable -pub struct BuiltinUnpermittedTypeInitSub { +pub(crate) struct BuiltinUnpermittedTypeInitSub { pub err: InitError, } @@ -463,7 +463,7 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { } #[derive(LintDiagnostic)] -pub enum BuiltinClashingExtern<'a> { +pub(crate) enum BuiltinClashingExtern<'a> { #[diag(lint_builtin_clashing_extern_same_name)] SameName { this: Symbol, @@ -489,7 +489,7 @@ pub enum BuiltinClashingExtern<'a> { } // FIXME(davidtwco): translatable expected/found -pub struct BuiltinClashingExternSub<'a> { +pub(crate) struct BuiltinClashingExternSub<'a> { pub tcx: TyCtxt<'a>, pub expected: Ty<'a>, pub found: Ty<'a>, @@ -511,7 +511,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { #[derive(LintDiagnostic)] #[diag(lint_builtin_deref_nullptr)] -pub struct BuiltinDerefNullptr { +pub(crate) struct BuiltinDerefNullptr { #[label] pub label: Span, } @@ -519,7 +519,7 @@ pub struct BuiltinDerefNullptr { // FIXME: migrate fluent::lint::builtin_asm_labels #[derive(LintDiagnostic)] -pub enum BuiltinSpecialModuleNameUsed { +pub(crate) enum BuiltinSpecialModuleNameUsed { #[diag(lint_builtin_special_module_name_used_lib)] #[note] #[help] @@ -532,7 +532,7 @@ pub enum BuiltinSpecialModuleNameUsed { // deref_into_dyn_supertrait.rs #[derive(LintDiagnostic)] #[diag(lint_supertrait_as_deref_target)] -pub struct SupertraitAsDerefTarget<'a> { +pub(crate) struct SupertraitAsDerefTarget<'a> { pub self_ty: Ty<'a>, pub supertrait_principal: PolyExistentialTraitRef<'a>, pub target_principal: PolyExistentialTraitRef<'a>, @@ -544,7 +544,7 @@ pub struct SupertraitAsDerefTarget<'a> { #[derive(Subdiagnostic)] #[label(lint_label2)] -pub struct SupertraitAsDerefTargetLabel { +pub(crate) struct SupertraitAsDerefTargetLabel { #[primary_span] pub label: Span, } @@ -552,7 +552,7 @@ pub struct SupertraitAsDerefTargetLabel { // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_discriminant)] -pub struct EnumIntrinsicsMemDiscriminate<'a> { +pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub ty_param: Ty<'a>, #[note] pub note: Span, @@ -561,14 +561,14 @@ pub struct EnumIntrinsicsMemDiscriminate<'a> { #[derive(LintDiagnostic)] #[diag(lint_enum_intrinsics_mem_variant)] #[note] -pub struct EnumIntrinsicsMemVariant<'a> { +pub(crate) struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } // expect.rs #[derive(LintDiagnostic)] #[diag(lint_expectation)] -pub struct Expectation { +pub(crate) struct Expectation { #[subdiagnostic] pub rationale: Option<ExpectationNote>, #[note] @@ -577,13 +577,13 @@ pub struct Expectation { #[derive(Subdiagnostic)] #[note(lint_rationale)] -pub struct ExpectationNote { +pub(crate) struct ExpectationNote { pub rationale: Symbol, } // ptr_nulls.rs #[derive(LintDiagnostic)] -pub enum PtrNullChecksDiag<'a> { +pub(crate) enum PtrNullChecksDiag<'a> { #[diag(lint_ptr_null_checks_fn_ptr)] #[help(lint_help)] FnPtr { @@ -604,7 +604,7 @@ pub enum PtrNullChecksDiag<'a> { // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] -pub struct ForLoopsOverFalliblesDiag<'a> { +pub(crate) struct ForLoopsOverFalliblesDiag<'a> { pub article: &'static str, pub ref_prefix: &'static str, pub ty: &'static str, @@ -617,7 +617,7 @@ pub struct ForLoopsOverFalliblesDiag<'a> { } #[derive(Subdiagnostic)] -pub enum ForLoopsOverFalliblesLoopSub<'a> { +pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] RemoveNext { #[primary_span] @@ -636,14 +636,14 @@ pub enum ForLoopsOverFalliblesLoopSub<'a> { #[derive(Subdiagnostic)] #[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")] -pub struct ForLoopsOverFalliblesQuestionMark { +pub(crate) struct ForLoopsOverFalliblesQuestionMark { #[primary_span] pub suggestion: Span, } #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] -pub struct ForLoopsOverFalliblesSuggestion<'a> { +pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { pub var: &'a str, #[suggestion_part(code = "if let {var}(")] pub start_span: Span, @@ -652,7 +652,7 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> { } #[derive(Subdiagnostic)] -pub enum UseLetUnderscoreIgnoreSuggestion { +pub(crate) enum UseLetUnderscoreIgnoreSuggestion { #[note(lint_use_let_underscore_ignore_suggestion)] Note, #[multipart_suggestion( @@ -671,7 +671,7 @@ pub enum UseLetUnderscoreIgnoreSuggestion { // drop_forget_useless.rs #[derive(LintDiagnostic)] #[diag(lint_dropping_references)] -pub struct DropRefDiag<'a> { +pub(crate) struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -681,7 +681,7 @@ pub struct DropRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -pub struct DropCopyDiag<'a> { +pub(crate) struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -691,7 +691,7 @@ pub struct DropCopyDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_forgetting_references)] -pub struct ForgetRefDiag<'a> { +pub(crate) struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -701,7 +701,7 @@ pub struct ForgetRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_forgetting_copy_types)] -pub struct ForgetCopyDiag<'a> { +pub(crate) struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -711,7 +711,7 @@ pub struct ForgetCopyDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_undropped_manually_drops)] -pub struct UndroppedManuallyDropsDiag<'a> { +pub(crate) struct UndroppedManuallyDropsDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, @@ -721,7 +721,7 @@ pub struct UndroppedManuallyDropsDiag<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct UndroppedManuallyDropsSuggestion { +pub(crate) struct UndroppedManuallyDropsSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -730,7 +730,7 @@ pub struct UndroppedManuallyDropsSuggestion { // invalid_from_utf8.rs #[derive(LintDiagnostic)] -pub enum InvalidFromUtf8Diag { +pub(crate) enum InvalidFromUtf8Diag { #[diag(lint_invalid_from_utf8_unchecked)] Unchecked { method: String, @@ -749,7 +749,7 @@ pub enum InvalidFromUtf8Diag { // reference_casting.rs #[derive(LintDiagnostic)] -pub enum InvalidReferenceCastingDiag<'tcx> { +pub(crate) enum InvalidReferenceCastingDiag<'tcx> { #[diag(lint_invalid_reference_casting_borrow_as_mut)] #[note(lint_invalid_reference_casting_note_book)] BorrowAsMut { @@ -784,7 +784,7 @@ pub enum InvalidReferenceCastingDiag<'tcx> { #[derive(LintDiagnostic)] #[diag(lint_hidden_unicode_codepoints)] #[note] -pub struct HiddenUnicodeCodepointsDiag<'a> { +pub(crate) struct HiddenUnicodeCodepointsDiag<'a> { pub label: &'a str, pub count: usize, #[label] @@ -795,7 +795,7 @@ pub struct HiddenUnicodeCodepointsDiag<'a> { pub sub: HiddenUnicodeCodepointsDiagSub, } -pub struct HiddenUnicodeCodepointsDiagLabels { +pub(crate) struct HiddenUnicodeCodepointsDiagLabels { pub spans: Vec<(char, Span)>, } @@ -811,7 +811,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { } } -pub enum HiddenUnicodeCodepointsDiagSub { +pub(crate) enum HiddenUnicodeCodepointsDiagSub { Escape { spans: Vec<(char, Span)> }, NoEscape { spans: Vec<(char, Span)> }, } @@ -866,7 +866,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { #[derive(LintDiagnostic)] #[diag(lint_map_unit_fn)] #[note] -pub struct MappingToUnit { +pub(crate) struct MappingToUnit { #[label(lint_function_label)] pub function_label: Span, #[label(lint_argument_label)] @@ -882,7 +882,7 @@ pub struct MappingToUnit { #[derive(LintDiagnostic)] #[diag(lint_default_hash_types)] #[note] -pub struct DefaultHashTypesDiag<'a> { +pub(crate) struct DefaultHashTypesDiag<'a> { pub preferred: &'a str, pub used: Symbol, } @@ -890,17 +890,17 @@ pub struct DefaultHashTypesDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_query_instability)] #[note] -pub struct QueryInstability { +pub(crate) struct QueryInstability { pub query: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_span_use_eq_ctxt)] -pub struct SpanUseEqCtxtDiag; +pub(crate) struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] -pub struct TykindKind { +pub(crate) struct TykindKind { #[suggestion(code = "ty", applicability = "maybe-incorrect")] pub suggestion: Span, } @@ -908,11 +908,11 @@ pub struct TykindKind { #[derive(LintDiagnostic)] #[diag(lint_tykind)] #[help] -pub struct TykindDiag; +pub(crate) struct TykindDiag; #[derive(LintDiagnostic)] #[diag(lint_ty_qualified)] -pub struct TyQualified { +pub(crate) struct TyQualified { pub ty: String, #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, @@ -920,7 +920,7 @@ pub struct TyQualified { #[derive(LintDiagnostic)] #[diag(lint_non_glob_import_type_ir_inherent)] -pub struct NonGlobImportTypeIrInherent { +pub(crate) struct NonGlobImportTypeIrInherent { #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")] pub suggestion: Option<Span>, pub snippet: &'static str, @@ -929,32 +929,32 @@ pub struct NonGlobImportTypeIrInherent { #[derive(LintDiagnostic)] #[diag(lint_lintpass_by_hand)] #[help] -pub struct LintPassByHand; +pub(crate) struct LintPassByHand; #[derive(LintDiagnostic)] #[diag(lint_non_existent_doc_keyword)] #[help] -pub struct NonExistentDocKeyword { +pub(crate) struct NonExistentDocKeyword { pub keyword: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_diag_out_of_impl)] -pub struct DiagOutOfImpl; +pub(crate) struct DiagOutOfImpl; #[derive(LintDiagnostic)] #[diag(lint_untranslatable_diag)] -pub struct UntranslatableDiag; +pub(crate) struct UntranslatableDiag; #[derive(LintDiagnostic)] #[diag(lint_bad_opt_access)] -pub struct BadOptAccessDiag<'a> { +pub(crate) struct BadOptAccessDiag<'a> { pub msg: &'a str, } // let_underscore.rs #[derive(LintDiagnostic)] -pub enum NonBindingLet { +pub(crate) enum NonBindingLet { #[diag(lint_non_binding_let_on_sync_lock)] SyncLock { #[label] @@ -969,7 +969,7 @@ pub enum NonBindingLet { }, } -pub struct NonBindingLetSub { +pub(crate) struct NonBindingLetSub { pub suggestion: Span, pub drop_fn_start_end: Option<(Span, Span)>, pub is_assign_desugar: bool, @@ -1012,7 +1012,7 @@ impl Subdiagnostic for NonBindingLetSub { // levels.rs #[derive(LintDiagnostic)] #[diag(lint_overruled_attribute)] -pub struct OverruledAttributeLint<'a> { +pub(crate) struct OverruledAttributeLint<'a> { #[label] pub overruled: Span, pub lint_level: &'a str, @@ -1023,7 +1023,7 @@ pub struct OverruledAttributeLint<'a> { #[derive(LintDiagnostic)] #[diag(lint_deprecated_lint_name)] -pub struct DeprecatedLintName<'a> { +pub(crate) struct DeprecatedLintName<'a> { pub name: String, #[suggestion(code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, @@ -1033,7 +1033,7 @@ pub struct DeprecatedLintName<'a> { #[derive(LintDiagnostic)] #[diag(lint_deprecated_lint_name)] #[help] -pub struct DeprecatedLintNameFromCommandLine<'a> { +pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { pub name: String, pub replace: &'a str, #[subdiagnostic] @@ -1042,14 +1042,14 @@ pub struct DeprecatedLintNameFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_renamed_lint)] -pub struct RenamedLint<'a> { +pub(crate) struct RenamedLint<'a> { pub name: &'a str, #[subdiagnostic] pub suggestion: RenamedLintSuggestion<'a>, } #[derive(Subdiagnostic)] -pub enum RenamedLintSuggestion<'a> { +pub(crate) enum RenamedLintSuggestion<'a> { #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] WithSpan { #[primary_span] @@ -1062,7 +1062,7 @@ pub enum RenamedLintSuggestion<'a> { #[derive(LintDiagnostic)] #[diag(lint_renamed_lint)] -pub struct RenamedLintFromCommandLine<'a> { +pub(crate) struct RenamedLintFromCommandLine<'a> { pub name: &'a str, #[subdiagnostic] pub suggestion: RenamedLintSuggestion<'a>, @@ -1072,14 +1072,14 @@ pub struct RenamedLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_removed_lint)] -pub struct RemovedLint<'a> { +pub(crate) struct RemovedLint<'a> { pub name: &'a str, pub reason: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_removed_lint)] -pub struct RemovedLintFromCommandLine<'a> { +pub(crate) struct RemovedLintFromCommandLine<'a> { pub name: &'a str, pub reason: &'a str, #[subdiagnostic] @@ -1088,14 +1088,14 @@ pub struct RemovedLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_unknown_lint)] -pub struct UnknownLint { +pub(crate) struct UnknownLint { pub name: String, #[subdiagnostic] pub suggestion: Option<UnknownLintSuggestion>, } #[derive(Subdiagnostic)] -pub enum UnknownLintSuggestion { +pub(crate) enum UnknownLintSuggestion { #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] WithSpan { #[primary_span] @@ -1109,7 +1109,7 @@ pub enum UnknownLintSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unknown_lint, code = E0602)] -pub struct UnknownLintFromCommandLine<'a> { +pub(crate) struct UnknownLintFromCommandLine<'a> { pub name: String, #[subdiagnostic] pub suggestion: Option<UnknownLintSuggestion>, @@ -1119,7 +1119,7 @@ pub struct UnknownLintFromCommandLine<'a> { #[derive(LintDiagnostic)] #[diag(lint_ignored_unless_crate_specified)] -pub struct IgnoredUnlessCrateSpecified<'a> { +pub(crate) struct IgnoredUnlessCrateSpecified<'a> { pub level: &'a str, pub name: Symbol, } @@ -1129,7 +1129,7 @@ pub struct IgnoredUnlessCrateSpecified<'a> { #[diag(lint_cstring_ptr)] #[note] #[help] -pub struct CStringPtr { +pub(crate) struct CStringPtr { #[label(lint_as_ptr_label)] pub as_ptr: Span, #[label(lint_unwrap_label)] @@ -1139,19 +1139,19 @@ pub struct CStringPtr { // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] #[diag(lint_multiple_supertrait_upcastable)] -pub struct MultipleSupertraitUpcastable { +pub(crate) struct MultipleSupertraitUpcastable { pub ident: Ident, } // non_ascii_idents.rs #[derive(LintDiagnostic)] #[diag(lint_identifier_non_ascii_char)] -pub struct IdentifierNonAsciiChar; +pub(crate) struct IdentifierNonAsciiChar; #[derive(LintDiagnostic)] #[diag(lint_identifier_uncommon_codepoints)] #[note] -pub struct IdentifierUncommonCodepoints { +pub(crate) struct IdentifierUncommonCodepoints { pub codepoints: Vec<char>, pub codepoints_len: usize, pub identifier_type: &'static str, @@ -1159,7 +1159,7 @@ pub struct IdentifierUncommonCodepoints { #[derive(LintDiagnostic)] #[diag(lint_confusable_identifier_pair)] -pub struct ConfusableIdentifierPair { +pub(crate) struct ConfusableIdentifierPair { pub existing_sym: Symbol, pub sym: Symbol, #[label(lint_other_use)] @@ -1172,13 +1172,13 @@ pub struct ConfusableIdentifierPair { #[diag(lint_mixed_script_confusables)] #[note(lint_includes_note)] #[note] -pub struct MixedScriptConfusables { +pub(crate) struct MixedScriptConfusables { pub set: String, pub includes: String, } // non_fmt_panic.rs -pub struct NonFmtPanicUnused { +pub(crate) struct NonFmtPanicUnused { pub count: usize, pub suggestion: Option<Span>, } @@ -1209,7 +1209,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { #[derive(LintDiagnostic)] #[diag(lint_non_fmt_panic_braces)] #[note] -pub struct NonFmtPanicBraces { +pub(crate) struct NonFmtPanicBraces { pub count: usize, #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")] pub suggestion: Option<Span>, @@ -1218,7 +1218,7 @@ pub struct NonFmtPanicBraces { // nonstandard_style.rs #[derive(LintDiagnostic)] #[diag(lint_non_camel_case_type)] -pub struct NonCamelCaseType<'a> { +pub(crate) struct NonCamelCaseType<'a> { pub sort: &'a str, pub name: &'a str, #[subdiagnostic] @@ -1226,7 +1226,7 @@ pub struct NonCamelCaseType<'a> { } #[derive(Subdiagnostic)] -pub enum NonCamelCaseTypeSub { +pub(crate) enum NonCamelCaseTypeSub { #[label(lint_label)] Label { #[primary_span] @@ -1242,7 +1242,7 @@ pub enum NonCamelCaseTypeSub { #[derive(LintDiagnostic)] #[diag(lint_non_snake_case)] -pub struct NonSnakeCaseDiag<'a> { +pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, pub name: &'a str, pub sc: String, @@ -1250,7 +1250,7 @@ pub struct NonSnakeCaseDiag<'a> { pub sub: NonSnakeCaseDiagSub, } -pub enum NonSnakeCaseDiagSub { +pub(crate) enum NonSnakeCaseDiagSub { Label { span: Span }, Help, RenameOrConvertSuggestion { span: Span, suggestion: Ident }, @@ -1302,7 +1302,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { #[derive(LintDiagnostic)] #[diag(lint_non_upper_case_global)] -pub struct NonUpperCaseGlobal<'a> { +pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str, pub name: &'a str, #[subdiagnostic] @@ -1310,7 +1310,7 @@ pub struct NonUpperCaseGlobal<'a> { } #[derive(Subdiagnostic)] -pub enum NonUpperCaseGlobalSub { +pub(crate) enum NonUpperCaseGlobalSub { #[label(lint_label)] Label { #[primary_span] @@ -1328,7 +1328,7 @@ pub enum NonUpperCaseGlobalSub { #[derive(LintDiagnostic)] #[diag(lint_noop_method_call)] #[note] -pub struct NoopMethodCallDiag<'a> { +pub(crate) struct NoopMethodCallDiag<'a> { pub method: Symbol, pub orig_ty: Ty<'a>, pub trait_: Symbol, @@ -1344,18 +1344,18 @@ pub struct NoopMethodCallDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_suspicious_double_ref_deref)] -pub struct SuspiciousDoubleRefDerefDiag<'a> { +pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] #[diag(lint_suspicious_double_ref_clone)] -pub struct SuspiciousDoubleRefCloneDiag<'a> { +pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { pub ty: Ty<'a>, } // non_local_defs.rs -pub enum NonLocalDefinitionsDiag { +pub(crate) enum NonLocalDefinitionsDiag { Impl { depth: u32, body_kind_descr: &'static str, @@ -1487,7 +1487,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { #[derive(Subdiagnostic)] #[note(lint_non_local_definitions_cargo_update)] -pub struct NonLocalDefinitionsCargoUpdateNote { +pub(crate) struct NonLocalDefinitionsCargoUpdateNote { pub macro_kind: &'static str, pub macro_name: Symbol, pub crate_name: Symbol, @@ -1497,7 +1497,7 @@ pub struct NonLocalDefinitionsCargoUpdateNote { #[derive(LintDiagnostic)] #[diag(lint_ambiguous_negative_literals)] #[note(lint_example)] -pub struct AmbiguousNegativeLiteralsDiag { +pub(crate) struct AmbiguousNegativeLiteralsDiag { #[subdiagnostic] pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, #[subdiagnostic] @@ -1506,7 +1506,7 @@ pub struct AmbiguousNegativeLiteralsDiag { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")] -pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { +pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -1515,7 +1515,7 @@ pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")] -pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { +pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, #[suggestion_part(code = ")")] @@ -1525,7 +1525,7 @@ pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { // pass_by_value.rs #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] -pub struct PassByValueDiag { +pub(crate) struct PassByValueDiag { pub ty: String, #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, @@ -1534,14 +1534,14 @@ pub struct PassByValueDiag { // redundant_semicolon.rs #[derive(LintDiagnostic)] #[diag(lint_redundant_semicolons)] -pub struct RedundantSemicolonsDiag { +pub(crate) struct RedundantSemicolonsDiag { pub multiple: bool, #[suggestion(code = "", applicability = "maybe-incorrect")] pub suggestion: Span, } // traits.rs -pub struct DropTraitConstraintsDiag<'a> { +pub(crate) struct DropTraitConstraintsDiag<'a> { pub predicate: Clause<'a>, pub tcx: TyCtxt<'a>, pub def_id: DefId, @@ -1556,7 +1556,7 @@ impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { } } -pub struct DropGlue<'a> { +pub(crate) struct DropGlue<'a> { pub tcx: TyCtxt<'a>, pub def_id: DefId, } @@ -1572,14 +1572,14 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { // types.rs #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] -pub struct RangeEndpointOutOfRange<'a> { +pub(crate) struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, #[subdiagnostic] pub sub: UseInclusiveRange<'a>, } #[derive(Subdiagnostic)] -pub enum UseInclusiveRange<'a> { +pub(crate) enum UseInclusiveRange<'a> { #[suggestion( lint_range_use_inclusive_range, code = "{start}..={literal}{suffix}", @@ -1605,7 +1605,7 @@ pub enum UseInclusiveRange<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_bin_hex)] -pub struct OverflowingBinHex<'a> { +pub(crate) struct OverflowingBinHex<'a> { pub ty: &'a str, pub lit: String, pub dec: u128, @@ -1618,7 +1618,7 @@ pub struct OverflowingBinHex<'a> { pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>, } -pub enum OverflowingBinHexSign { +pub(crate) enum OverflowingBinHexSign { Positive, Negative, } @@ -1642,7 +1642,7 @@ impl Subdiagnostic for OverflowingBinHexSign { } #[derive(Subdiagnostic)] -pub enum OverflowingBinHexSub<'a> { +pub(crate) enum OverflowingBinHexSub<'a> { #[suggestion( lint_suggestion, code = "{sans_suffix}{suggestion_ty}", @@ -1664,7 +1664,7 @@ pub enum OverflowingBinHexSub<'a> { code = "{lit_no_suffix}{uint_ty} as {int_ty}", applicability = "maybe-incorrect" )] -pub struct OverflowingBinHexSignBitSub<'a> { +pub(crate) struct OverflowingBinHexSignBitSub<'a> { #[primary_span] pub span: Span, pub lit_no_suffix: &'a str, @@ -1676,7 +1676,7 @@ pub struct OverflowingBinHexSignBitSub<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_int)] #[note] -pub struct OverflowingInt<'a> { +pub(crate) struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, pub min: i128, @@ -1687,13 +1687,13 @@ pub struct OverflowingInt<'a> { #[derive(Subdiagnostic)] #[help(lint_help)] -pub struct OverflowingIntHelp<'a> { +pub(crate) struct OverflowingIntHelp<'a> { pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] #[diag(lint_only_cast_u8_to_char)] -pub struct OnlyCastu8ToChar { +pub(crate) struct OnlyCastu8ToChar { #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")] pub span: Span, pub literal: u128, @@ -1702,7 +1702,7 @@ pub struct OnlyCastu8ToChar { #[derive(LintDiagnostic)] #[diag(lint_overflowing_uint)] #[note] -pub struct OverflowingUInt<'a> { +pub(crate) struct OverflowingUInt<'a> { pub ty: &'a str, pub lit: String, pub min: u128, @@ -1712,17 +1712,17 @@ pub struct OverflowingUInt<'a> { #[derive(LintDiagnostic)] #[diag(lint_overflowing_literal)] #[note] -pub struct OverflowingLiteral<'a> { +pub(crate) struct OverflowingLiteral<'a> { pub ty: &'a str, pub lit: String, } #[derive(LintDiagnostic)] #[diag(lint_unused_comparisons)] -pub struct UnusedComparisons; +pub(crate) struct UnusedComparisons; #[derive(LintDiagnostic)] -pub enum InvalidNanComparisons { +pub(crate) enum InvalidNanComparisons { #[diag(lint_invalid_nan_comparisons_eq_ne)] EqNe { #[subdiagnostic] @@ -1733,7 +1733,7 @@ pub enum InvalidNanComparisons { } #[derive(Subdiagnostic)] -pub enum InvalidNanComparisonsSuggestion { +pub(crate) enum InvalidNanComparisonsSuggestion { #[multipart_suggestion( lint_suggestion, style = "verbose", @@ -1752,7 +1752,7 @@ pub enum InvalidNanComparisonsSuggestion { } #[derive(LintDiagnostic)] -pub enum AmbiguousWidePointerComparisons<'a> { +pub(crate) enum AmbiguousWidePointerComparisons<'a> { #[diag(lint_ambiguous_wide_pointer_comparisons)] Spanful { #[subdiagnostic] @@ -1773,7 +1773,7 @@ pub enum AmbiguousWidePointerComparisons<'a> { // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" )] -pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { +pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { pub ne: &'a str, pub deref_left: &'a str, pub deref_right: &'a str, @@ -1788,7 +1788,7 @@ pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { } #[derive(Subdiagnostic)] -pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { +pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { #[multipart_suggestion( lint_addr_suggestion, style = "verbose", @@ -1832,7 +1832,7 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { }, } -pub struct ImproperCTypes<'a> { +pub(crate) struct ImproperCTypes<'a> { pub ty: Ty<'a>, pub desc: &'a str, pub label: Span, @@ -1860,29 +1860,29 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { #[derive(LintDiagnostic)] #[diag(lint_variant_size_differences)] -pub struct VariantSizeDifferencesDiag { +pub(crate) struct VariantSizeDifferencesDiag { pub largest: u64, } #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_load)] #[help] -pub struct AtomicOrderingLoad; +pub(crate) struct AtomicOrderingLoad; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_store)] #[help] -pub struct AtomicOrderingStore; +pub(crate) struct AtomicOrderingStore; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_fence)] #[help] -pub struct AtomicOrderingFence; +pub(crate) struct AtomicOrderingFence; #[derive(LintDiagnostic)] #[diag(lint_atomic_ordering_invalid)] #[help] -pub struct InvalidAtomicOrderingDiag { +pub(crate) struct InvalidAtomicOrderingDiag { pub method: Symbol, #[label] pub fail_order_arg_span: Span, @@ -1891,7 +1891,7 @@ pub struct InvalidAtomicOrderingDiag { // unused.rs #[derive(LintDiagnostic)] #[diag(lint_unused_op)] -pub struct UnusedOp<'a> { +pub(crate) struct UnusedOp<'a> { pub op: &'a str, #[label] pub label: Span, @@ -1900,7 +1900,7 @@ pub struct UnusedOp<'a> { } #[derive(Subdiagnostic)] -pub enum UnusedOpSuggestion { +pub(crate) enum UnusedOpSuggestion { #[suggestion( lint_suggestion, style = "verbose", @@ -1922,7 +1922,7 @@ pub enum UnusedOpSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unused_result)] -pub struct UnusedResult<'a> { +pub(crate) struct UnusedResult<'a> { pub ty: Ty<'a>, } @@ -1931,7 +1931,7 @@ pub struct UnusedResult<'a> { #[derive(LintDiagnostic)] #[diag(lint_unused_closure)] #[note] -pub struct UnusedClosure<'a> { +pub(crate) struct UnusedClosure<'a> { pub count: usize, pub pre: &'a str, pub post: &'a str, @@ -1942,7 +1942,7 @@ pub struct UnusedClosure<'a> { #[derive(LintDiagnostic)] #[diag(lint_unused_coroutine)] #[note] -pub struct UnusedCoroutine<'a> { +pub(crate) struct UnusedCoroutine<'a> { pub count: usize, pub pre: &'a str, pub post: &'a str, @@ -1950,7 +1950,7 @@ pub struct UnusedCoroutine<'a> { // FIXME(davidtwco): this isn't properly translatable because of the pre/post // strings -pub struct UnusedDef<'a, 'b> { +pub(crate) struct UnusedDef<'a, 'b> { pub pre: &'a str, pub post: &'a str, pub cx: &'a LateContext<'b>, @@ -1961,7 +1961,7 @@ pub struct UnusedDef<'a, 'b> { #[derive(Subdiagnostic)] -pub enum UnusedDefSuggestion { +pub(crate) enum UnusedDefSuggestion { #[suggestion( lint_suggestion, style = "verbose", @@ -2000,13 +2000,13 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { #[derive(LintDiagnostic)] #[diag(lint_path_statement_drop)] -pub struct PathStatementDrop { +pub(crate) struct PathStatementDrop { #[subdiagnostic] pub sub: PathStatementDropSub, } #[derive(Subdiagnostic)] -pub enum PathStatementDropSub { +pub(crate) enum PathStatementDropSub { #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")] Suggestion { #[primary_span] @@ -2022,11 +2022,11 @@ pub enum PathStatementDropSub { #[derive(LintDiagnostic)] #[diag(lint_path_statement_no_effect)] -pub struct PathStatementNoEffect; +pub(crate) struct PathStatementNoEffect; #[derive(LintDiagnostic)] #[diag(lint_unused_delim)] -pub struct UnusedDelim<'a> { +pub(crate) struct UnusedDelim<'a> { pub delim: &'static str, pub item: &'a str, #[subdiagnostic] @@ -2035,7 +2035,7 @@ pub struct UnusedDelim<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct UnusedDelimSuggestion { +pub(crate) struct UnusedDelimSuggestion { #[suggestion_part(code = "{start_replace}")] pub start_span: Span, pub start_replace: &'static str, @@ -2046,19 +2046,19 @@ pub struct UnusedDelimSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unused_import_braces)] -pub struct UnusedImportBracesDiag { +pub(crate) struct UnusedImportBracesDiag { pub node: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_unused_allocation)] -pub struct UnusedAllocationDiag; +pub(crate) struct UnusedAllocationDiag; #[derive(LintDiagnostic)] #[diag(lint_unused_allocation_mut)] -pub struct UnusedAllocationMutDiag; +pub(crate) struct UnusedAllocationMutDiag; -pub struct AsyncFnInTraitDiag { +pub(crate) struct AsyncFnInTraitDiag { pub sugg: Option<Vec<(Span, String)>>, } @@ -2074,13 +2074,13 @@ impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag { #[derive(LintDiagnostic)] #[diag(lint_unit_bindings)] -pub struct UnitBindingsDiag { +pub(crate) struct UnitBindingsDiag { #[label] pub label: Span, } #[derive(LintDiagnostic)] -pub enum InvalidAsmLabel { +pub(crate) enum InvalidAsmLabel { #[diag(lint_invalid_asm_label_named)] #[help] #[note] @@ -2110,7 +2110,7 @@ pub enum InvalidAsmLabel { } #[derive(Subdiagnostic)] -pub enum UnexpectedCfgCargoHelp { +pub(crate) enum UnexpectedCfgCargoHelp { #[help(lint_unexpected_cfg_add_cargo_feature)] #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] LintCfg { cargo_toml_lint_cfg: String }, @@ -2127,13 +2127,13 @@ impl UnexpectedCfgCargoHelp { ) } - pub fn lint_cfg(unescaped: &str) -> Self { + pub(crate) fn lint_cfg(unescaped: &str) -> Self { UnexpectedCfgCargoHelp::LintCfg { cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), } } - pub fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self { + pub(crate) fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self { UnexpectedCfgCargoHelp::LintCfgAndBuildRs { cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped), build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"), @@ -2143,19 +2143,19 @@ impl UnexpectedCfgCargoHelp { #[derive(Subdiagnostic)] #[help(lint_unexpected_cfg_add_cmdline_arg)] -pub struct UnexpectedCfgRustcHelp { +pub(crate) struct UnexpectedCfgRustcHelp { pub cmdline_arg: String, } impl UnexpectedCfgRustcHelp { - pub fn new(unescaped: &str) -> Self { + pub(crate) fn new(unescaped: &str) -> Self { Self { cmdline_arg: format!("--check-cfg={unescaped}") } } } #[derive(LintDiagnostic)] #[diag(lint_unexpected_cfg_name)] -pub struct UnexpectedCfgName { +pub(crate) struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, #[subdiagnostic] @@ -2164,13 +2164,13 @@ pub struct UnexpectedCfgName { pub name: Symbol, } -pub mod unexpected_cfg_name { +pub(crate) mod unexpected_cfg_name { use rustc_errors::DiagSymbolList; use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] - pub enum CodeSuggestion { + pub(crate) enum CodeSuggestion { #[help(lint_unexpected_cfg_define_features)] DefineFeatures, #[suggestion( @@ -2227,7 +2227,7 @@ pub mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[help(lint_unexpected_cfg_name_expected_values)] - pub struct ExpectedValues { + pub(crate) struct ExpectedValues { pub best_match: Symbol, pub possibilities: DiagSymbolList, } @@ -2238,7 +2238,7 @@ pub mod unexpected_cfg_name { applicability = "maybe-incorrect", code = "{code}" )] - pub struct FoundWithSimilarValue { + pub(crate) struct FoundWithSimilarValue { #[primary_span] pub span: Span, pub code: String, @@ -2246,13 +2246,13 @@ pub mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[help_once(lint_unexpected_cfg_name_expected_names)] - pub struct ExpectedNames { + pub(crate) struct ExpectedNames { pub possibilities: DiagSymbolList, pub and_more: usize, } #[derive(Subdiagnostic)] - pub enum InvocationHelp { + pub(crate) enum InvocationHelp { #[note(lint_unexpected_cfg_doc_cargo)] Cargo { #[subdiagnostic] @@ -2265,7 +2265,7 @@ pub mod unexpected_cfg_name { #[derive(LintDiagnostic)] #[diag(lint_unexpected_cfg_value)] -pub struct UnexpectedCfgValue { +pub(crate) struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, #[subdiagnostic] @@ -2275,13 +2275,13 @@ pub struct UnexpectedCfgValue { pub value: String, } -pub mod unexpected_cfg_value { +pub(crate) mod unexpected_cfg_value { use rustc_errors::DiagSymbolList; use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] - pub enum CodeSuggestion { + pub(crate) enum CodeSuggestion { ChangeValue { #[subdiagnostic] expected_values: ExpectedValues, @@ -2305,7 +2305,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum ChangeValueSuggestion { + pub(crate) enum ChangeValueSuggestion { #[suggestion( lint_unexpected_cfg_value_similar_name, code = r#""{best_match}""#, @@ -2334,7 +2334,7 @@ pub mod unexpected_cfg_value { code = "", applicability = "maybe-incorrect" )] - pub struct RemoveValueSuggestion { + pub(crate) struct RemoveValueSuggestion { #[primary_span] pub span: Span, } @@ -2345,14 +2345,14 @@ pub mod unexpected_cfg_value { code = "", applicability = "maybe-incorrect" )] - pub struct RemoveConditionSuggestion { + pub(crate) struct RemoveConditionSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] #[note(lint_unexpected_cfg_value_expected_values)] - pub struct ExpectedValues { + pub(crate) struct ExpectedValues { pub name: Symbol, pub have_none_possibility: bool, pub possibilities: DiagSymbolList, @@ -2360,7 +2360,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum InvocationHelp { + pub(crate) enum InvocationHelp { #[note(lint_unexpected_cfg_doc_cargo)] Cargo(#[subdiagnostic] Option<CargoHelp>), #[note(lint_unexpected_cfg_doc_rustc)] @@ -2368,7 +2368,7 @@ pub mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - pub enum CargoHelp { + pub(crate) enum CargoHelp { #[help(lint_unexpected_cfg_value_add_feature)] AddFeature { value: Symbol, @@ -2383,7 +2383,7 @@ pub mod unexpected_cfg_value { #[diag(lint_unexpected_builtin_cfg)] #[note(lint_controlled_by)] #[note(lint_incoherent)] -pub struct UnexpectedBuiltinCfg { +pub(crate) struct UnexpectedBuiltinCfg { pub(crate) cfg: String, pub(crate) cfg_name: Symbol, pub(crate) controlled_by: &'static str, @@ -2392,15 +2392,15 @@ pub struct UnexpectedBuiltinCfg { #[derive(LintDiagnostic)] #[diag(lint_macro_use_deprecated)] #[help] -pub struct MacroUseDeprecated; +pub(crate) struct MacroUseDeprecated; #[derive(LintDiagnostic)] #[diag(lint_unused_macro_use)] -pub struct UnusedMacroUse; +pub(crate) struct UnusedMacroUse; #[derive(LintDiagnostic)] #[diag(lint_private_extern_crate_reexport, code = E0365)] -pub struct PrivateExternCrateReexport { +pub(crate) struct PrivateExternCrateReexport { pub ident: Ident, #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] pub sugg: Span, @@ -2408,28 +2408,28 @@ pub struct PrivateExternCrateReexport { #[derive(LintDiagnostic)] #[diag(lint_unused_label)] -pub struct UnusedLabel; +pub(crate) struct UnusedLabel; #[derive(LintDiagnostic)] #[diag(lint_macro_is_private)] -pub struct MacroIsPrivate { +pub(crate) struct MacroIsPrivate { pub ident: Ident, } #[derive(LintDiagnostic)] #[diag(lint_unused_macro_definition)] -pub struct UnusedMacroDefinition { +pub(crate) struct UnusedMacroDefinition { pub name: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_macro_rule_never_used)] -pub struct MacroRuleNeverUsed { +pub(crate) struct MacroRuleNeverUsed { pub n: usize, pub name: Symbol, } -pub struct UnstableFeature { +pub(crate) struct UnstableFeature { pub msg: DiagMessage, } @@ -2441,81 +2441,81 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { #[derive(LintDiagnostic)] #[diag(lint_avoid_intel_syntax)] -pub struct AvoidIntelSyntax; +pub(crate) struct AvoidIntelSyntax; #[derive(LintDiagnostic)] #[diag(lint_avoid_att_syntax)] -pub struct AvoidAttSyntax; +pub(crate) struct AvoidAttSyntax; #[derive(LintDiagnostic)] #[diag(lint_incomplete_include)] -pub struct IncompleteInclude; +pub(crate) struct IncompleteInclude; #[derive(LintDiagnostic)] #[diag(lint_unnameable_test_items)] -pub struct UnnameableTestItems; +pub(crate) struct UnnameableTestItems; #[derive(LintDiagnostic)] #[diag(lint_duplicate_macro_attribute)] -pub struct DuplicateMacroAttribute; +pub(crate) struct DuplicateMacroAttribute; #[derive(LintDiagnostic)] #[diag(lint_cfg_attr_no_attributes)] -pub struct CfgAttrNoAttributes; +pub(crate) struct CfgAttrNoAttributes; #[derive(LintDiagnostic)] #[diag(lint_crate_type_in_cfg_attr_deprecated)] -pub struct CrateTypeInCfgAttr; +pub(crate) struct CrateTypeInCfgAttr; #[derive(LintDiagnostic)] #[diag(lint_crate_name_in_cfg_attr_deprecated)] -pub struct CrateNameInCfgAttr; +pub(crate) struct CrateNameInCfgAttr; #[derive(LintDiagnostic)] #[diag(lint_missing_fragment_specifier)] -pub struct MissingFragmentSpecifier; +pub(crate) struct MissingFragmentSpecifier; #[derive(LintDiagnostic)] #[diag(lint_metavariable_still_repeating)] -pub struct MetaVariableStillRepeating { +pub(crate) struct MetaVariableStillRepeating { pub name: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] #[diag(lint_metavariable_wrong_operator)] -pub struct MetaVariableWrongOperator; +pub(crate) struct MetaVariableWrongOperator; #[derive(LintDiagnostic)] #[diag(lint_duplicate_matcher_binding)] -pub struct DuplicateMatcherBinding; +pub(crate) struct DuplicateMatcherBinding; #[derive(LintDiagnostic)] #[diag(lint_unknown_macro_variable)] -pub struct UnknownMacroVariable { +pub(crate) struct UnknownMacroVariable { pub name: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] #[diag(lint_unused_crate_dependency)] #[help] -pub struct UnusedCrateDependency { +pub(crate) struct UnusedCrateDependency { pub extern_crate: Symbol, pub local_crate: Symbol, } #[derive(LintDiagnostic)] #[diag(lint_wasm_c_abi)] -pub struct WasmCAbi; +pub(crate) struct WasmCAbi; #[derive(LintDiagnostic)] #[diag(lint_ill_formed_attribute_input)] -pub struct IllFormedAttributeInput { +pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, pub suggestions: DiagArgValue, } #[derive(LintDiagnostic)] -pub enum InnerAttributeUnstable { +pub(crate) enum InnerAttributeUnstable { #[diag(lint_inner_macro_attribute_unstable)] InnerMacroAttribute, #[diag(lint_custom_inner_attribute_unstable)] @@ -2524,7 +2524,7 @@ pub enum InnerAttributeUnstable { #[derive(LintDiagnostic)] #[diag(lint_unknown_diagnostic_attribute)] -pub struct UnknownDiagnosticAttribute { +pub(crate) struct UnknownDiagnosticAttribute { #[subdiagnostic] pub typo: Option<UnknownDiagnosticAttributeTypoSugg>, } @@ -2536,7 +2536,7 @@ pub struct UnknownDiagnosticAttribute { code = "{typo_name}", applicability = "machine-applicable" )] -pub struct UnknownDiagnosticAttributeTypoSugg { +pub(crate) struct UnknownDiagnosticAttributeTypoSugg { #[primary_span] pub span: Span, pub typo_name: Symbol, @@ -2545,7 +2545,7 @@ pub struct UnknownDiagnosticAttributeTypoSugg { #[derive(LintDiagnostic)] #[diag(lint_unicode_text_flow)] #[note] -pub struct UnicodeTextFlow { +pub(crate) struct UnicodeTextFlow { #[label] pub comment_span: Span, #[subdiagnostic] @@ -2558,7 +2558,7 @@ pub struct UnicodeTextFlow { #[derive(Subdiagnostic)] #[label(lint_label_comment_char)] -pub struct UnicodeCharNoteSub { +pub(crate) struct UnicodeCharNoteSub { #[primary_span] pub span: Span, pub c_debug: String, @@ -2566,21 +2566,21 @@ pub struct UnicodeCharNoteSub { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] -pub struct UnicodeTextFlowSuggestion { +pub(crate) struct UnicodeTextFlowSuggestion { #[suggestion_part(code = "")] pub spans: Vec<Span>, } #[derive(LintDiagnostic)] #[diag(lint_abs_path_with_module)] -pub struct AbsPathWithModule { +pub(crate) struct AbsPathWithModule { #[subdiagnostic] pub sugg: AbsPathWithModuleSugg, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = "{replacement}")] -pub struct AbsPathWithModuleSugg { +pub(crate) struct AbsPathWithModuleSugg { #[primary_span] pub span: Span, #[applicability] @@ -2590,7 +2590,7 @@ pub struct AbsPathWithModuleSugg { #[derive(LintDiagnostic)] #[diag(lint_proc_macro_derive_resolution_fallback)] -pub struct ProcMacroDeriveResolutionFallback { +pub(crate) struct ProcMacroDeriveResolutionFallback { #[label] pub span: Span, pub ns: Namespace, @@ -2599,28 +2599,28 @@ pub struct ProcMacroDeriveResolutionFallback { #[derive(LintDiagnostic)] #[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)] -pub struct MacroExpandedMacroExportsAccessedByAbsolutePaths { +pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths { #[note] pub definition: Span, } #[derive(LintDiagnostic)] #[diag(lint_hidden_lifetime_parameters)] -pub struct ElidedLifetimesInPaths { +pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: ElidedLifetimeInPathSubdiag, } #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] -pub struct UnknownCrateTypes { +pub(crate) struct UnknownCrateTypes { #[subdiagnostic] pub sugg: Option<UnknownCrateTypesSub>, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")] -pub struct UnknownCrateTypesSub { +pub(crate) struct UnknownCrateTypesSub { #[primary_span] pub span: Span, pub candidate: Symbol, @@ -2628,7 +2628,7 @@ pub struct UnknownCrateTypesSub { #[derive(LintDiagnostic)] #[diag(lint_unused_imports)] -pub struct UnusedImports { +pub(crate) struct UnusedImports { #[subdiagnostic] pub sugg: UnusedImportsSugg, #[help] @@ -2639,7 +2639,7 @@ pub struct UnusedImports { } #[derive(Subdiagnostic)] -pub enum UnusedImportsSugg { +pub(crate) enum UnusedImportsSugg { #[suggestion( lint_suggestion_remove_whole_use, applicability = "machine-applicable", @@ -2664,7 +2664,7 @@ pub enum UnusedImportsSugg { #[derive(LintDiagnostic)] #[diag(lint_redundant_import)] -pub struct RedundantImport { +pub(crate) struct RedundantImport { #[subdiagnostic] pub subs: Vec<RedundantImportSub>, @@ -2672,7 +2672,7 @@ pub struct RedundantImport { } #[derive(Subdiagnostic)] -pub enum RedundantImportSub { +pub(crate) enum RedundantImportSub { #[label(lint_label_imported_here)] ImportedHere(#[primary_span] Span), #[label(lint_label_defined_here)] @@ -2686,13 +2686,13 @@ pub enum RedundantImportSub { #[derive(LintDiagnostic)] #[diag(lint_unused_doc_comment)] #[help] -pub struct UnusedDocComment { +pub(crate) struct UnusedDocComment { #[label] pub span: Span, } #[derive(LintDiagnostic)] -pub enum PatternsInFnsWithoutBody { +pub(crate) enum PatternsInFnsWithoutBody { #[diag(lint_pattern_in_foreign)] Foreign { #[subdiagnostic] @@ -2707,7 +2707,7 @@ pub enum PatternsInFnsWithoutBody { #[derive(Subdiagnostic)] #[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] -pub struct PatternsInFnsWithoutBodySub { +pub(crate) struct PatternsInFnsWithoutBodySub { #[primary_span] pub span: Span, @@ -2717,7 +2717,7 @@ pub struct PatternsInFnsWithoutBodySub { #[derive(LintDiagnostic)] #[diag(lint_extern_without_abi)] #[help] -pub struct MissingAbi { +pub(crate) struct MissingAbi { #[label] pub span: Span, @@ -2726,14 +2726,14 @@ pub struct MissingAbi { #[derive(LintDiagnostic)] #[diag(lint_legacy_derive_helpers)] -pub struct LegacyDeriveHelpers { +pub(crate) struct LegacyDeriveHelpers { #[label] pub span: Span, } #[derive(LintDiagnostic)] #[diag(lint_or_patterns_back_compat)] -pub struct OrPatternsBackCompat { +pub(crate) struct OrPatternsBackCompat { #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] pub span: Span, pub suggestion: String, @@ -2741,7 +2741,7 @@ pub struct OrPatternsBackCompat { #[derive(LintDiagnostic)] #[diag(lint_reserved_prefix)] -pub struct ReservedPrefix { +pub(crate) struct ReservedPrefix { #[label] pub label: Span, #[suggestion(code = " ", applicability = "machine-applicable")] @@ -2752,7 +2752,7 @@ pub struct ReservedPrefix { #[derive(LintDiagnostic)] #[diag(lint_unused_builtin_attribute)] -pub struct UnusedBuiltinAttribute { +pub(crate) struct UnusedBuiltinAttribute { #[note] pub invoc_span: Span, @@ -2762,7 +2762,7 @@ pub struct UnusedBuiltinAttribute { #[derive(LintDiagnostic)] #[diag(lint_trailing_semi_macro)] -pub struct TrailingMacro { +pub(crate) struct TrailingMacro { #[note(lint_note1)] #[note(lint_note2)] pub is_trailing: bool, @@ -2772,14 +2772,14 @@ pub struct TrailingMacro { #[derive(LintDiagnostic)] #[diag(lint_break_with_label_and_loop)] -pub struct BreakWithLabelAndLoop { +pub(crate) struct BreakWithLabelAndLoop { #[subdiagnostic] pub sub: BreakWithLabelAndLoopSub, } #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct BreakWithLabelAndLoopSub { +pub(crate) struct BreakWithLabelAndLoopSub { #[suggestion_part(code = "(")] pub left: Span, #[suggestion_part(code = ")")] @@ -2789,13 +2789,13 @@ pub struct BreakWithLabelAndLoopSub { #[derive(LintDiagnostic)] #[diag(lint_deprecated_where_clause_location)] #[note] -pub struct DeprecatedWhereClauseLocation { +pub(crate) struct DeprecatedWhereClauseLocation { #[subdiagnostic] pub suggestion: DeprecatedWhereClauseLocationSugg, } #[derive(Subdiagnostic)] -pub enum DeprecatedWhereClauseLocationSugg { +pub(crate) enum DeprecatedWhereClauseLocationSugg { #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] MoveToEnd { #[suggestion_part(code = "")] @@ -2814,14 +2814,14 @@ pub enum DeprecatedWhereClauseLocationSugg { #[derive(LintDiagnostic)] #[diag(lint_missing_unsafe_on_extern)] -pub struct MissingUnsafeOnExtern { +pub(crate) struct MissingUnsafeOnExtern { #[suggestion(code = "unsafe ", applicability = "machine-applicable")] pub suggestion: Span, } #[derive(LintDiagnostic)] #[diag(lint_single_use_lifetime)] -pub struct SingleUseLifetime { +pub(crate) struct SingleUseLifetime { #[label(lint_label_param)] pub param_span: Span, #[label(lint_label_use)] @@ -2834,7 +2834,7 @@ pub struct SingleUseLifetime { #[derive(Subdiagnostic)] #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -pub struct SingleUseLifetimeSugg { +pub(crate) struct SingleUseLifetimeSugg { #[suggestion_part(code = "")] pub deletion_span: Option<Span>, #[suggestion_part(code = "{replace_lt}")] @@ -2845,7 +2845,7 @@ pub struct SingleUseLifetimeSugg { #[derive(LintDiagnostic)] #[diag(lint_unused_lifetime)] -pub struct UnusedLifetime { +pub(crate) struct UnusedLifetime { #[suggestion(code = "", applicability = "machine-applicable")] pub deletion_span: Option<Span>, @@ -2854,7 +2854,7 @@ pub struct UnusedLifetime { #[derive(LintDiagnostic)] #[diag(lint_named_argument_used_positionally)] -pub struct NamedArgumentUsedPositionally { +pub(crate) struct NamedArgumentUsedPositionally { #[label(lint_label_named_arg)] pub named_arg_sp: Span, #[label(lint_label_position_arg)] @@ -2869,21 +2869,21 @@ pub struct NamedArgumentUsedPositionally { #[derive(LintDiagnostic)] #[diag(lint_byte_slice_in_packed_struct_with_derive)] #[help] -pub struct ByteSliceInPackedStructWithDerive { +pub(crate) struct ByteSliceInPackedStructWithDerive { // FIXME: make this translatable pub ty: String, } #[derive(LintDiagnostic)] #[diag(lint_unused_extern_crate)] -pub struct UnusedExternCrate { +pub(crate) struct UnusedExternCrate { #[suggestion(code = "", applicability = "machine-applicable")] pub removal_span: Span, } #[derive(LintDiagnostic)] #[diag(lint_extern_crate_not_idiomatic)] -pub struct ExternCrateNotIdiomatic { +pub(crate) struct ExternCrateNotIdiomatic { #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] pub span: Span, @@ -2891,7 +2891,7 @@ pub struct ExternCrateNotIdiomatic { } // FIXME: make this translatable -pub struct AmbiguousGlobImports { +pub(crate) struct AmbiguousGlobImports { pub ambiguity: AmbiguityErrorDiag, } @@ -2904,7 +2904,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for AmbiguousGlobImports { #[derive(LintDiagnostic)] #[diag(lint_ambiguous_glob_reexport)] -pub struct AmbiguousGlobReexports { +pub(crate) struct AmbiguousGlobReexports { #[label(lint_label_first_reexport)] pub first_reexport: Span, #[label(lint_label_duplicate_reexport)] @@ -2917,7 +2917,7 @@ pub struct AmbiguousGlobReexports { #[derive(LintDiagnostic)] #[diag(lint_hidden_glob_reexport)] -pub struct HiddenGlobReexports { +pub(crate) struct HiddenGlobReexports { #[note(lint_note_glob_reexport)] pub glob_reexport: Span, #[note(lint_note_private_item)] @@ -2930,14 +2930,14 @@ pub struct HiddenGlobReexports { #[derive(LintDiagnostic)] #[diag(lint_unnecessary_qualification)] -pub struct UnusedQualifications { +pub(crate) struct UnusedQualifications { #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] pub removal_span: Span, } #[derive(LintDiagnostic)] #[diag(lint_associated_const_elided_lifetime)] -pub struct AssociatedConstElidedLifetime { +pub(crate) struct AssociatedConstElidedLifetime { #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] pub span: Span, @@ -2949,7 +2949,7 @@ pub struct AssociatedConstElidedLifetime { #[derive(LintDiagnostic)] #[diag(lint_redundant_import_visibility)] -pub struct RedundantImportVisibility { +pub(crate) struct RedundantImportVisibility { #[note] pub span: Span, #[help] @@ -2961,7 +2961,7 @@ pub struct RedundantImportVisibility { #[derive(LintDiagnostic)] #[diag(lint_unsafe_attr_outside_unsafe)] -pub struct UnsafeAttrOutsideUnsafe { +pub(crate) struct UnsafeAttrOutsideUnsafe { #[label] pub span: Span, #[subdiagnostic] @@ -2973,7 +2973,7 @@ pub struct UnsafeAttrOutsideUnsafe { lint_unsafe_attr_outside_unsafe_suggestion, applicability = "machine-applicable" )] -pub struct UnsafeAttrOutsideUnsafeSuggestion { +pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, #[suggestion_part(code = ")")] @@ -2983,6 +2983,6 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion { #[derive(LintDiagnostic)] #[diag(lint_out_of_scope_macro_calls)] #[help] -pub struct OutOfScopeMacroCalls { +pub(crate) struct OutOfScopeMacroCalls { pub path: String, } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 5ad677995da..13a3c741fe3 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -55,7 +55,7 @@ declare_lint! { } #[derive(Default)] -pub struct NonLocalDefinitions { +pub(crate) struct NonLocalDefinitions { body_depth: u32, } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index d7fd41c0ad7..d81052b5e24 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -17,13 +17,13 @@ use crate::lints::{ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; #[derive(PartialEq)] -pub enum MethodLateContext { +pub(crate) enum MethodLateContext { TraitAutoImpl, TraitImpl, PlainImpl, } -pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { +pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext { let item = cx.tcx.associated_item(id); match item.container { ty::TraitContainer => MethodLateContext::TraitAutoImpl, diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index 4fe35a6a0a3..bb9c7d85c2e 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -65,7 +65,7 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct ShadowedIntoIter; +pub(crate) struct ShadowedIntoIter; impl_lint_pass!(ShadowedIntoIter => [ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER]); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index cb7a07116ce..f2f7c0eaa4d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -165,7 +165,7 @@ declare_lint! { } #[derive(Copy, Clone)] -pub struct TypeLimits { +pub(crate) struct TypeLimits { /// Id of the last visited negated expression negated_expr_id: Option<hir::HirId>, /// Span of the last visited negated expression @@ -180,7 +180,7 @@ impl_lint_pass!(TypeLimits => [ ]); impl TypeLimits { - pub fn new() -> TypeLimits { + pub(crate) fn new() -> TypeLimits { TypeLimits { negated_expr_id: None, negated_expr_span: None } } } @@ -985,6 +985,14 @@ struct ImproperCTypesVisitor<'a, 'tcx> { mode: CItemKind, } +/// Accumulator for recursive ffi type checking +struct CTypesVisitorState<'tcx> { + cache: FxHashSet<Ty<'tcx>>, + /// The original type being checked, before we recursed + /// to any other types it contains. + base_ty: Ty<'tcx>, +} + enum FfiResult<'tcx> { FfiSafe, FfiPhantom(Ty<'tcx>), @@ -1000,7 +1008,7 @@ pub(crate) fn nonnull_optimization_guaranteed<'tcx>( /// `repr(transparent)` structs can have a single non-1-ZST field, this function returns that /// field. -pub fn transparent_newtype_field<'a, 'tcx>( +pub(crate) fn transparent_newtype_field<'a, 'tcx>( tcx: TyCtxt<'tcx>, variant: &'a ty::VariantDef, ) -> Option<&'a ty::FieldDef> { @@ -1213,7 +1221,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given field's type is "ffi-safe". fn check_field_type_for_ffi( &self, - cache: &mut FxHashSet<Ty<'tcx>>, + acc: &mut CTypesVisitorState<'tcx>, field: &ty::FieldDef, args: GenericArgsRef<'tcx>, ) -> FfiResult<'tcx> { @@ -1223,13 +1231,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { .tcx .try_normalize_erasing_regions(self.cx.param_env, field_ty) .unwrap_or(field_ty); - self.check_type_for_ffi(cache, field_ty) + self.check_type_for_ffi(acc, field_ty) } /// Checks if the given `VariantDef`'s field types are "ffi-safe". fn check_variant_for_ffi( &self, - cache: &mut FxHashSet<Ty<'tcx>>, + acc: &mut CTypesVisitorState<'tcx>, ty: Ty<'tcx>, def: ty::AdtDef<'tcx>, variant: &ty::VariantDef, @@ -1239,7 +1247,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let transparent_with_all_zst_fields = if def.repr().transparent() { if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { // Transparent newtypes have at most one non-ZST field which needs to be checked.. - match self.check_field_type_for_ffi(cache, field, args) { + match self.check_field_type_for_ffi(acc, field, args) { FfiUnsafe { ty, .. } if ty.is_unit() => (), r => return r, } @@ -1257,7 +1265,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // We can't completely trust `repr(C)` markings, so make sure the fields are actually safe. let mut all_phantom = !variant.fields.is_empty(); for field in &variant.fields { - all_phantom &= match self.check_field_type_for_ffi(cache, field, args) { + all_phantom &= match self.check_field_type_for_ffi(acc, field, args) { FfiSafe => false, // `()` fields are FFI-safe! FfiUnsafe { ty, .. } if ty.is_unit() => false, @@ -1277,7 +1285,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { /// Checks if the given type is "ffi-safe" (has a stable, well-defined /// representation which can be exported to C code). - fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> FfiResult<'tcx> { + fn check_type_for_ffi( + &self, + acc: &mut CTypesVisitorState<'tcx>, + ty: Ty<'tcx>, + ) -> FfiResult<'tcx> { use FfiResult::*; let tcx = self.cx.tcx; @@ -1286,7 +1298,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // `struct S(*mut S);`. // FIXME: A recursion limit is necessary as well, for irregular // recursive types. - if !cache.insert(ty) { + if !acc.cache.insert(ty) { return FfiSafe; } @@ -1308,6 +1320,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct | AdtKind::Union => { + if let Some(sym::cstring_type | sym::cstr_type) = + tcx.get_diagnostic_name(def.did()) + && !acc.base_ty.is_mutable_ptr() + { + return FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_cstr_reason, + help: Some(fluent::lint_improper_ctypes_cstr_help), + }; + } + if !def.repr().c() && !def.repr().transparent() { return FfiUnsafe { ty, @@ -1354,7 +1377,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - self.check_variant_for_ffi(cache, ty, def, def.non_enum_variant(), args) + self.check_variant_for_ffi(acc, ty, def, def.non_enum_variant(), args) } AdtKind::Enum => { if def.variants().is_empty() { @@ -1378,7 +1401,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = repr_nullable_ptr(self.cx.tcx, self.cx.param_env, ty, self.mode) { - return self.check_type_for_ffi(cache, ty); + return self.check_type_for_ffi(acc, ty); } return FfiUnsafe { @@ -1399,7 +1422,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - match self.check_variant_for_ffi(cache, ty, def, variant, args) { + match self.check_variant_for_ffi(acc, ty, def, variant, args) { FfiSafe => (), r => return r, } @@ -1469,9 +1492,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty), + ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(acc, ty), - ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty), + ty::Array(inner_ty, _) => self.check_type_for_ffi(acc, inner_ty), ty::FnPtr(sig_tys, hdr) => { let sig = sig_tys.with(hdr); @@ -1485,7 +1508,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = tcx.instantiate_bound_regions_with_erased(sig); for arg in sig.inputs() { - match self.check_type_for_ffi(cache, *arg) { + match self.check_type_for_ffi(acc, *arg) { FfiSafe => {} r => return r, } @@ -1496,7 +1519,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } - self.check_type_for_ffi(cache, ret_ty) + self.check_type_for_ffi(acc, ret_ty) } ty::Foreign(..) => FfiSafe, @@ -1619,7 +1642,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return; } - match self.check_type_for_ffi(&mut FxHashSet::default(), ty) { + let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty }; + match self.check_type_for_ffi(&mut acc, ty) { FfiResult::FfiSafe => {} FfiResult::FfiPhantom(ty) => { self.emit_ffi_unsafe_type_lint( diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 553d9db12c5..c3b80e01c36 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1019,7 +1019,7 @@ declare_lint! { "`if`, `match`, `while` and `return` do not need parentheses" } -pub struct UnusedParens { +pub(crate) struct UnusedParens { with_self_ty_parens: bool, /// `1 as (i32) < 2` parses to ExprKind::Lt /// `1 as i32 < 2` parses to i32::<2[missing angle bracket] @@ -1027,7 +1027,7 @@ pub struct UnusedParens { } impl UnusedParens { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { with_self_ty_parens: false, parens_in_cast_in_lt: Vec::new() } } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 56d77c9d1d0..44c72e0c4fe 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -142,7 +142,6 @@ declare_lint_pass! { USELESS_DEPRECATED, WARNINGS, WASM_C_ABI, - WRITES_THROUGH_IMMUTABLE_POINTER, // tidy-alphabetical-end ] } @@ -251,7 +250,7 @@ declare_lint! { Deny, "conflicts between `#[repr(..)]` hints that were previously accepted and used in practice", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>", }; } @@ -4697,40 +4696,6 @@ declare_lint! { } declare_lint! { - /// The `writes_through_immutable_pointer` lint detects writes through pointers derived from - /// shared references. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![feature(const_mut_refs)] - /// const WRITE_AFTER_CAST: () = unsafe { - /// let mut x = 0; - /// let ptr = &x as *const i32 as *mut i32; - /// *ptr = 0; - /// }; - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Shared references are immutable (when there is no `UnsafeCell` involved), - /// and writing through them or through pointers derived from them is Undefined Behavior. - /// The compiler recently learned to detect such Undefined Behavior during compile-time - /// evaluation, and in the future this will raise a hard error. - /// - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub WRITES_THROUGH_IMMUTABLE_POINTER, - Warn, - "shared references are immutable, and pointers derived from them must not be written to", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #X <https://github.com/rust-lang/rust/issues/X>", - }; -} - -declare_lint! { /// The `private_macro_use` lint detects private macros that are imported /// with `#[macro_use]`. /// diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0f07de43e80..c17b85db3b0 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,3 +1,7 @@ +// tidy-alphabetical-start +#![warn(unreachable_pub)] +// tidy-alphabetical-end + use rustc_ast::node_id::NodeId; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 83fda7ef07c..1f74aaf9965 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -10,5 +10,5 @@ libc = "0.2.73" [build-dependencies] # tidy-alphabetical-start -cc = "1.0.97" +cc = "=1.0.105" # FIXME(cc): pinned to keep support for VS2013 # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 283c4fbbb7c..9884ed15b8a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1607,8 +1607,13 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const auto &ExportList = Data->ExportLists.lookup(ModId); const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId); +#if LLVM_VERSION_GE(20, 0) + DenseSet<GlobalValue::GUID> CfiFunctionDefs; + DenseSet<GlobalValue::GUID> CfiFunctionDecls; +#else std::set<GlobalValue::GUID> CfiFunctionDefs; std::set<GlobalValue::GUID> CfiFunctionDecls; +#endif // Based on the 'InProcessThinBackend' constructor in LLVM for (auto &Name : Data->Index.cfiFunctionDefs()) @@ -1618,9 +1623,15 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, CfiFunctionDecls.insert( GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); +#if LLVM_VERSION_GE(20, 0) + Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList, + ExportList, ResolvedODR, DefinedGlobals, + CfiFunctionDefs, CfiFunctionDecls); +#else llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls); +#endif LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size()); } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 79a68b2ff0e..ed12318c88d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -913,14 +913,19 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, - const char *Checksum, size_t ChecksumLen) { + const char *Checksum, size_t ChecksumLen, + const char *Source, size_t SourceLen) { std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind); std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{}; if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); + std::optional<StringRef> oSource{}; + if (Source) + oSource = StringRef(Source, SourceLen); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), CSInfo)); + StringRef(Directory, DirectoryLen), CSInfo, + oSource)); } extern "C" LLVMMetadataRef diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 939e5e4dbd4..3532d50c64e 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,8 +1,10 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(unsafe_attributes, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // NOTE: This crate only exists to allow linking on mingw targets. @@ -28,7 +30,7 @@ impl RustString { } /// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn LLVMRustStringWriteImpl( sr: &RustString, ptr: *const c_char, @@ -46,7 +48,7 @@ pub fn initialize_available_targets() { ($cfg:meta, $($method:ident),*) => { { #[cfg($cfg)] fn init() { - extern "C" { + unsafe extern "C" { $(fn $method();)* } unsafe { diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index c59f86b0a9b..929bc2df6f6 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -1,7 +1,5 @@ // tidy-alphabetical-start -#![allow(internal_features)] #![allow(rustc::default_hash_types)] -#![feature(allow_internal_unstable)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 8c0ea3eaea9..a13eac08c9f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1487,7 +1487,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> + '_ { + fn get_foreign_modules(self, sess: &'a Session) -> impl Iterator<Item = ForeignModule> + 'a { self.root.foreign_modules.decode((self, sess)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 46039f6e5f6..27625f79108 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -224,6 +224,7 @@ provide! { tcx, def_id, other, cdata, variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } + struct_target_features => { table } impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0d83f8c6c5c..fbcfbd3befa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -872,7 +872,8 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::OpaqueTy | DefKind::Field | DefKind::Impl { .. } - | DefKind::Closure => true, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => true, DefKind::ForeignMod | DefKind::GlobalAsm => false, } } @@ -902,6 +903,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { // https://github.com/model-checking/kani and is not a performance // or maintenance issue for us. DefKind::Closure => true, + DefKind::SyntheticCoroutineBody => false, DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(..) @@ -948,7 +950,8 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => false, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => false, } } @@ -984,7 +987,8 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1019,7 +1023,8 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1061,6 +1066,7 @@ fn should_encode_mir( } // Coroutines require optimized MIR to compute layout. DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true), + DefKind::SyntheticCoroutineBody => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { let generics = tcx.generics_of(def_id); @@ -1109,7 +1115,8 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } @@ -1137,7 +1144,8 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::Field | DefKind::TyParam - | DefKind::Closure => true, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => true, DefKind::Mod | DefKind::ForeignMod | DefKind::ConstParam @@ -1168,7 +1176,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Closure | DefKind::ConstParam | DefKind::AnonConst - | DefKind::InlineConst => true, + | DefKind::InlineConst + | DefKind::SyntheticCoroutineBody => true, DefKind::OpaqueTy => { let origin = tcx.opaque_type_origin(def_id); @@ -1240,7 +1249,8 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1277,7 +1287,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1310,7 +1321,8 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::ExternCrate => false, + | DefKind::ExternCrate + | DefKind::SyntheticCoroutineBody => false, } } @@ -1380,6 +1392,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } + if def_kind.has_struct_target_features() { + record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id)); + } if should_encode_visibility(def_kind) { let vis = self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); @@ -1458,7 +1473,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id); } } - if def_kind == DefKind::Closure + if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index c1b77172983..aec728d4262 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_macros::{ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; @@ -427,6 +427,7 @@ define_tables! { variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, + struct_target_features: Table<DefIndex, LazyArray<TargetFeature>>, impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>, const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, rustc_middle::ty::Const<'static>>>>, object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 617372a97b5..3a6f3543317 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -171,6 +171,7 @@ fixed_size_enum! { ( Macro(MacroKind::Bang) ) ( Macro(MacroKind::Attr) ) ( Macro(MacroKind::Derive) ) + ( SyntheticCoroutineBody ) } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 37c10b14054..7050a06b8dc 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -35,7 +35,6 @@ macro_rules! arena_types { )>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, [] region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 0f85998204c..3d346b9cc5d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -307,7 +307,7 @@ impl<'hir> Map<'hir> { } DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, - DefKind::Closure => BodyOwnerKind::Closure, + DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure, DefKind::Static { safety: _, mutability, nested: false } => { BodyOwnerKind::Static(mutability) } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5bd7736a3f3..ce330b4744b 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,12 +28,13 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] +#![cfg_attr(bootstrap, feature(min_exhaustive_patterns, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] +#![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] #![feature(const_option)] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b7d290e58d2..c098a739592 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,8 @@ pub struct CodegenFnAttrs { /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option<u16>, - /// The `#[target_feature(enable = "...")]` attribute and the enabled - /// features (only enabled features are supported right now). + /// All the target features that are enabled for this function. Some features might be enabled + /// implicitly. pub target_features: Vec<TargetFeature>, /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option<Linkage>, @@ -55,8 +55,8 @@ pub struct CodegenFnAttrs { pub struct TargetFeature { /// The name of the target feature (e.g. "avx") pub name: Symbol, - /// The feature is implied by another feature, rather than explicitly added by the - /// `#[target_feature]` attribute + /// The feature is implied by another feature or by an argument, rather than explicitly + /// added by the `#[target_feature]` attribute pub implied: bool, } diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index a4f6d7afe4d..32e2f3b4b16 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; @@ -11,9 +11,9 @@ use crate::ty; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] pub enum ResolvedArg { StaticLifetime, - EarlyBound(/* decl */ DefId), - LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), - Free(DefId, /* lifetime decl */ DefId), + EarlyBound(/* decl */ LocalDefId), + LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ LocalDefId), + Free(LocalDefId, /* lifetime decl */ LocalDefId), Error(ErrorGuaranteed), } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index b11c523cfe9..bfe2a2c2cb3 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -163,7 +163,7 @@ impl Debug for CoverageKind { #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] #[derive(TypeFoldable, TypeVisitable)] -pub struct CodeRegion { +pub struct SourceRegion { pub file_name: Symbol, pub start_line: u32, pub start_col: u32, @@ -171,7 +171,7 @@ pub struct CodeRegion { pub end_col: u32, } -impl Debug for CodeRegion { +impl Debug for SourceRegion { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!( fmt, @@ -242,7 +242,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub code_region: CodeRegion, + pub source_region: SourceRegion, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 665ab2797f2..3e101c0c635 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -62,13 +62,11 @@ impl AllocBytes for Box<[u8]> { } fn as_mut_ptr(&mut self) -> *mut u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of_mut!(**self).cast() + Box::as_mut_ptr(self).cast() } fn as_ptr(&self) -> *const u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of!(**self).cast() + Box::as_ptr(self).cast() } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5b2aac781eb..7b901915037 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -267,18 +267,6 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option<Body<'tcx>>, - /// The body of the coroutine, modified to take its upvars by move rather than by ref. - /// - /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which - /// is run right after building the initial MIR, and will only be populated for coroutines - /// which come out of the async closure desugaring. - /// - /// This body should be processed in lockstep with the containing body -- any optimization - /// passes, etc, should be applied to this body as well. This is done automatically if - /// using `run_passes`. - pub by_move_body: Option<Body<'tcx>>, - /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option<CoroutineLayout<'tcx>>, @@ -298,7 +286,6 @@ impl<'tcx> CoroutineInfo<'tcx> { coroutine_kind, yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), - by_move_body: None, coroutine_drop: None, coroutine_layout: None, } @@ -665,10 +652,6 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref()) } - pub fn coroutine_by_move_body(&self) -> Option<&Body<'tcx>> { - self.coroutine.as_ref()?.by_move_body.as_ref() - } - #[inline] pub fn coroutine_kind(&self) -> Option<CoroutineKind> { self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 336a9388a56..1d94c364ae3 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -415,7 +415,6 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceKind::Virtual(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index efdc0c710ba..6785805c27d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -547,8 +547,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, code_region } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?; + for coverage::Mapping { kind, source_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index bfb129495ce..64898a8495e 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -349,7 +349,6 @@ macro_rules! make_mir_visitor { coroutine_closure_def_id: _def_id, receiver_by_ref: _, } | - ty::InstanceKind::CoroutineKindShim { coroutine_def_id: _def_id } | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) | ty::InstanceKind::DropGlue(_def_id, None) => {} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 75166624f95..6434bd0d7bf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,7 +47,7 @@ use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::CodegenFnAttrs; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; @@ -312,20 +312,10 @@ rustc_queries! { /// predicates (where-clauses) that must be proven true in order /// to reference it. This is almost always the "predicates query" /// that you want. - /// - /// `predicates_of` builds on `predicates_defined_on` -- in fact, - /// it is almost always the same as that query, except for the - /// case of traits. For traits, `predicates_of` contains - /// an additional `Self: Trait<...>` predicate that users don't - /// actually write. This reflects the fact that to invoke the - /// trait (e.g., via `Default::default`) you must supply types - /// that actually implement the trait. (However, this extra - /// predicate gets in the way of some checks, which are intended - /// to operate over only the actual where-clauses written by the - /// user.) query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + feedable } query opaque_types_defined_by( @@ -498,6 +488,7 @@ rustc_queries! { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html query mir_built(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> { desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } + feedable } /// Try to build an abstract representation of the given constant. @@ -617,14 +608,6 @@ rustc_queries! { desc { "getting wasm import module map" } } - /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the - /// predicates (where-clauses) directly defined on it. This is - /// equal to the `explicit_predicates_of` predicates plus the - /// `inferred_outlives_of` predicates. - query predicates_defined_on(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } - } - /// Returns everything that looks like a predicate written explicitly /// by the user on a trait item. /// @@ -742,6 +725,7 @@ rustc_queries! { query constness(key: DefId) -> hir::Constness { desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } separate_provide_extern + feedable } query asyncness(key: DefId) -> ty::Asyncness { @@ -760,10 +744,22 @@ rustc_queries! { desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } } + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { + desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. query coroutine_kind(def_id: DefId) -> Option<hir::CoroutineKind> { desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } separate_provide_extern + feedable } query coroutine_for_closure(def_id: DefId) -> DefId { @@ -1249,6 +1245,11 @@ rustc_queries! { feedable } + query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] { + separate_provide_extern + desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) } + } + query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d54e2ca0a74..a3277fb96d2 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -353,7 +353,7 @@ pub enum ObligationCauseCode<'tcx> { ReturnValue(HirId), /// Opaque return type of this function - OpaqueReturnType(Option<(Ty<'tcx>, Span)>), + OpaqueReturnType(Option<(Ty<'tcx>, HirId)>), /// Block implicit return BlockTailExpression(HirId, hir::MatchSource), diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 401f6da6526..46203ee150f 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -462,7 +462,6 @@ impl_decodable_via_ref! { &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion, &'tcx ty::List<ty::BoundVariableKind>, &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>, &'tcx ty::List<FieldIdx>, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index e373292741b..362ff8e988d 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -240,7 +240,7 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - match Self::try_from_lit(tcx, ty, expr) { + match Self::try_from_lit_or_param(tcx, ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated( tcx, @@ -281,7 +281,11 @@ impl<'tcx> Const<'tcx> { } #[instrument(skip(tcx), level = "debug")] - fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> { + fn try_from_lit_or_param( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Option<Self> { // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments // currently have to be wrapped in curly brackets, so it's necessary to special-case. let expr = match &expr.kind { @@ -291,6 +295,22 @@ impl<'tcx> Const<'tcx> { _ => expr, }; + if let hir::ExprKind::Path( + qpath @ hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + ), + ) = expr.kind + { + if tcx.features().const_arg_path { + span_bug!( + expr.span, + "try_from_lit: received const param which shouldn't be possible" + ); + } + return Some(Const::from_param(tcx, qpath, expr.hir_id)); + }; + let lit_input = match expr.kind { hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { @@ -318,14 +338,6 @@ impl<'tcx> Const<'tcx> { } } - if let hir::ExprKind::Path(hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - )) = expr.kind - { - span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible") - } - None } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9b39b849704..8effb67a1f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1579,6 +1579,12 @@ impl<'tcx> TyCtxt<'tcx> { ) } + // Whether the body owner is synthetic, which in this case means it does not correspond to + // meaningful HIR. This is currently used to skip over MIR borrowck. + pub fn is_synthetic_mir(self, def_id: impl Into<DefId>) -> bool { + matches!(self.def_kind(def_id.into()), DefKind::SyntheticCoroutineBody) + } + /// Returns `true` if the node pointed to by `def_id` is a general coroutine that implements `Coroutine`. /// This means it is neither an `async` or `gen` construct. pub fn is_general_coroutine(self, def_id: DefId) -> bool { @@ -3035,13 +3041,13 @@ impl<'tcx> TyCtxt<'tcx> { match self.named_bound_var(lifetime.hir_id) { Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => { - let new_parent = self.parent(ebv); + let new_parent = self.local_parent(ebv); // If we map to another opaque, then it should be a parent // of the opaque we mapped from. Continue mapping. if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { - debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); - opaque_lifetime_param_def_id = ebv.expect_local(); + debug_assert_eq!(self.local_parent(parent), new_parent); + opaque_lifetime_param_def_id = ebv; continue; } @@ -3050,20 +3056,20 @@ impl<'tcx> TyCtxt<'tcx> { self, ty::EarlyParamRegion { index: generics - .param_def_id_to_index(self, ebv) + .param_def_id_to_index(self, ebv.to_def_id()) .expect("early-bound var should be present in fn generics"), - name: self.hir().name(self.local_def_id_to_hir_id(ebv.expect_local())), + name: self.item_name(ebv.to_def_id()), }, ); } Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => { - let new_parent = self.parent(lbv); + let new_parent = self.local_parent(lbv); return ty::Region::new_late_param( self, - new_parent, + new_parent.to_def_id(), ty::BoundRegionKind::BrNamed( - lbv, - self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())), + lbv.to_def_id(), + self.item_name(lbv.to_def_id()), ), ); } @@ -3168,6 +3174,18 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } + pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool { + if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + self.coroutine_kind(def_id) + && let ty::Coroutine(_, args) = self.type_of(def_id).instantiate_identity().kind() + && args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce) + { + true + } else { + false + } + } + /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 8cb8e9af11c..bbc696e0f08 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -269,7 +269,7 @@ impl<'tcx> Generics { } /// Returns the `GenericParamDef` associated with this `ParamConst`. - pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { + pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { GenericParamDefKind::Const { .. } => param, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index ecb3943e788..7d5f0f1e9c4 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -141,14 +141,6 @@ pub enum InstanceKind<'tcx> { receiver_by_ref: bool, }, - /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` - /// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or - /// similarly for `AsyncFnMut`. - /// - /// This will select the body that is produced by the `ByMoveBody` transform, and thus - /// take and use all of its upvars by-move rather than by-ref. - CoroutineKindShim { coroutine_def_id: DefId }, - /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -248,7 +240,6 @@ impl<'tcx> InstanceKind<'tcx> { coroutine_closure_def_id: def_id, receiver_by_ref: _, } - | ty::InstanceKind::CoroutineKindShim { coroutine_def_id: def_id } | InstanceKind::DropGlue(def_id, _) | InstanceKind::CloneShim(def_id, _) | InstanceKind::FnPtrAddrShim(def_id, _) @@ -270,7 +261,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) @@ -377,7 +367,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false, InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::Item(_) @@ -452,7 +441,6 @@ pub fn fmt_instance( InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"), InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), - InstanceKind::CoroutineKindShim { .. } => write!(f, " - shim"), InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -850,7 +838,9 @@ impl<'tcx> Instance<'tcx> { Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args }) } else { Some(Instance { - def: ty::InstanceKind::CoroutineKindShim { coroutine_def_id }, + def: ty::InstanceKind::Item( + tcx.coroutine_by_move_body_def_id(coroutine_def_id), + ), args, }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 619981bf021..d0a9039441d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1104,7 +1104,7 @@ where } fn is_never(this: TyAndLayout<'tcx>) -> bool { - this.ty.kind() == &ty::Never + matches!(this.ty.kind(), ty::Never) } fn is_tuple(this: TyAndLayout<'tcx>) -> bool { diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 1a1acf36d77..af76d5b7d92 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -58,7 +58,7 @@ impl<T> Default for &List<T> { } } -extern "C" { +unsafe extern "C" { /// A dummy type used to force `List` to be unsized while not requiring /// references to it be wide pointers. type OpaqueListContents; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1e3b5800cba..e41ea7507ef 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1756,7 +1756,6 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceKind::Virtual(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) | ty::InstanceKind::ThreadLocalShim(..) @@ -1874,7 +1873,8 @@ impl<'tcx> TyCtxt<'tcx> { identity_kind_ty.to_opt_closure_kind(), Some(ClosureKind::Fn | ClosureKind::FnMut) ); - mir.coroutine_by_move_body().unwrap().coroutine_layout_raw() + self.optimized_mir(self.coroutine_by_move_body_def_id(def_id)) + .coroutine_layout_raw() } } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 7e1255f606c..be611e19b49 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, + crate::middle::codegen_fn_attrs::TargetFeature, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::lib_features::FeatureStability, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 319fb7ef03b..f1ff90831b0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3119,7 +3119,10 @@ define_print! { ty::ExistentialProjection<'tcx> { let name = cx.tcx().associated_item(self.def_id).name; - p!(write("{} = ", name), print(self.term)) + // The args don't contain the self ty (as it has been erased) but the corresp. + // generics do as the trait always has a self ty param. We need to offset. + let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..]; + p!(path_generic_args(|cx| write!(cx, "{name}"), args), " = ", print(self.term)) } ty::ProjectionPredicate<'tcx> { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 045c8ad39be..efbccca77c1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -296,7 +296,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> (Ty<'tcx>, Ty<'tcx>) { let (mut a, mut b) = (source, target); loop { - match (&a.kind(), &b.kind()) { + match (a.kind(), b.kind()) { (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) if a_def == b_def && a_def.is_struct() => { diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 7a10e627ccd..a42e8ff0168 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -125,6 +125,17 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + +mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + initializing type with `target_feature` attr is unsafe and requires unsafe function or block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + + mir_build_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior @@ -387,6 +398,11 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 4430aab73a8..4f1166f9111 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -127,7 +127,7 @@ fn lit_to_mir_constant<'tcx>( Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) }; - let value = match (lit, &ty.kind()) { + let value = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b6cf7a40ecd..60cd49b88b4 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -461,14 +461,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id)); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { - // If the called function has target features the calling function hasn't, + // If the called function has explicit target features the calling function hasn't, // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs + // Implicit target features are OK because they are either a consequence of some + // explicit target feature (which is checked to be present in the caller) or + // come from a witness argument. let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm && !callee_features.iter().all(|feature| { - self.body_target_features.iter().any(|f| f.name == feature.name) + feature.implied + || self.body_target_features.iter().any(|f| f.name == feature.name) }) { let missing: Vec<_> = callee_features @@ -542,10 +546,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { user_ty: _, fields: _, base: _, - }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.requires_unsafe(expr.span, InitializingTypeWith), - }, + }) => { + match self.tcx.layout_scalar_valid_range(adt_def.did()) { + (Bound::Unbounded, Bound::Unbounded) => {} + _ => self.requires_unsafe(expr.span, InitializingTypeWith), + } + if !self.tcx.struct_target_features(adt_def.did()).is_empty() { + self.requires_unsafe(expr.span, ConstructingTargetFeaturesType) + } + } + ExprKind::Closure(box ClosureExpr { closure_id, args: _, @@ -647,6 +657,7 @@ enum UnsafeOpKind { CallToUnsafeFunction(Option<DefId>), UseOfInlineAssembly, InitializingTypeWith, + ConstructingTargetFeaturesType, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -728,6 +739,15 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), + ConstructingTargetFeaturesType => tcx.emit_node_span_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, + ), UseOfMutableStatic => tcx.emit_node_span_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, @@ -885,6 +905,20 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } + ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => { + dcx.emit_err( + InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, + ); + } + ConstructingTargetFeaturesType => { + dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); + } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 843ac2eb240..e7d6239aa9b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -87,6 +87,16 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { } #[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, +} + +#[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { @@ -251,6 +261,17 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe { } #[derive(Diagnostic)] +#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, +} + +#[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133 @@ -265,6 +286,20 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] +#[diag( + mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = E0133 +)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, +} + +#[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UseOfMutableStaticRequiresUnsafe { @@ -493,7 +528,7 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); diag.span(self.scrut_span); diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 7b94867114d..b8877a64e47 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -29,7 +29,7 @@ pub(crate) fn lit_to_const<'tcx>( .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))) }; - let valtree = match (lit, &ty.kind()) { + let valtree = match (lit, ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 703339bf5bc..d9d2abc554a 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -53,7 +53,7 @@ mod by_move_body; use std::{iter, ops}; -pub use by_move_body::ByMoveBody; +pub use by_move_body::coroutine_by_move_body_def_id; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 7ea36f08232..ebe8d2eff4f 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -69,161 +69,167 @@ //! in case precise captures (edition 2021 closure capture rules) caused the inner coroutine //! to split one field capture into two. +use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::{self, dump_mir, MirPass}; +use rustc_middle::mir::{self, dump_mir}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::symbol::kw; use rustc_target::abi::{FieldIdx, VariantIdx}; -use crate::pass_manager::validate_body; - -pub struct ByMoveBody; +pub fn coroutine_by_move_body_def_id<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_def_id: LocalDefId, +) -> DefId { + let body = tcx.mir_built(coroutine_def_id).borrow(); -impl<'tcx> MirPass<'tcx> for ByMoveBody { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - // We only need to generate by-move coroutine bodies for coroutines that come - // from coroutine-closures. - let Some(coroutine_def_id) = body.source.def_id().as_local() else { - return; - }; - let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = - tcx.coroutine_kind(coroutine_def_id) - else { - return; - }; + let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + tcx.coroutine_kind(coroutine_def_id) + else { + bug!("should only be invoked on coroutine-closures"); + }; - // Also, let's skip processing any bodies with errors, since there's no guarantee - // the MIR body will be constructed well. - let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - if coroutine_ty.references_error() { - return; - } + // Also, let's skip processing any bodies with errors, since there's no guarantee + // the MIR body will be constructed well. + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - // We don't need to generate a by-move coroutine if the coroutine body was - // produced by the `CoroutineKindShim`, since it's already by-move. - if matches!(body.source.instance, ty::InstanceKind::CoroutineKindShim { .. }) { - return; - } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + let args = args.as_coroutine(); - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; - let args = args.as_coroutine(); + let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); - let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); + let parent_def_id = tcx.local_parent(coroutine_def_id); + let ty::CoroutineClosure(_, parent_args) = + *tcx.type_of(parent_def_id).instantiate_identity().kind() + else { + bug!(); + }; + if parent_args.references_error() { + return coroutine_def_id.to_def_id(); + } - let parent_def_id = tcx.local_parent(coroutine_def_id); - let ty::CoroutineClosure(_, parent_args) = - *tcx.type_of(parent_def_id).instantiate_identity().kind() - else { - bug!(); - }; - let parent_closure_args = parent_args.as_coroutine_closure(); - let num_args = parent_closure_args - .coroutine_closure_sig() - .skip_binder() - .tupled_inputs_ty - .tuple_fields() - .len(); + let parent_closure_args = parent_args.as_coroutine_closure(); + let num_args = parent_closure_args + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(); - let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( - tcx.closure_captures(parent_def_id).iter().copied(), - tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), - |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { - // Store this set of additional projections (fields and derefs). - // We need to re-apply them later. - let mut child_precise_captures = child_capture.place.projections - [parent_capture.place.projections.len()..] - .to_vec(); + let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( + tcx.closure_captures(parent_def_id).iter().copied(), + tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), + |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { + // Store this set of additional projections (fields and derefs). + // We need to re-apply them later. + let mut child_precise_captures = + child_capture.place.projections[parent_capture.place.projections.len()..].to_vec(); - // If the parent capture is by-ref, then we need to apply an additional - // deref before applying any further projections to this place. - if parent_capture.is_by_ref() { - child_precise_captures.insert( - 0, - Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref }, - ); - } - // If the child capture is by-ref, then we need to apply a "ref" - // projection (i.e. `&`) at the end. But wait! We don't have that - // as a projection kind. So instead, we can apply its dual and - // *peel* a deref off of the place when it shows up in the MIR body. - // Luckily, by construction this is always possible. - let peel_deref = if child_capture.is_by_ref() { - assert!( - parent_capture.is_by_ref() || coroutine_kind != ty::ClosureKind::FnOnce, - "`FnOnce` coroutine-closures return coroutines that capture from \ + // If the parent capture is by-ref, then we need to apply an additional + // deref before applying any further projections to this place. + if parent_capture.is_by_ref() { + child_precise_captures.insert( + 0, + Projection { ty: parent_capture.place.ty(), kind: ProjectionKind::Deref }, + ); + } + // If the child capture is by-ref, then we need to apply a "ref" + // projection (i.e. `&`) at the end. But wait! We don't have that + // as a projection kind. So instead, we can apply its dual and + // *peel* a deref off of the place when it shows up in the MIR body. + // Luckily, by construction this is always possible. + let peel_deref = if child_capture.is_by_ref() { + assert!( + parent_capture.is_by_ref() || coroutine_kind != ty::ClosureKind::FnOnce, + "`FnOnce` coroutine-closures return coroutines that capture from \ their body; it will always result in a borrowck error!" - ); - true - } else { - false - }; + ); + true + } else { + false + }; - // Regarding the behavior above, you may think that it's redundant to both - // insert a deref and then peel a deref if the parent and child are both - // captured by-ref. This would be correct, except for the case where we have - // precise capturing projections, since the inserted deref is to the *beginning* - // and the peeled deref is at the *end*. I cannot seem to actually find a - // case where this happens, though, but let's keep this code flexible. + // Regarding the behavior above, you may think that it's redundant to both + // insert a deref and then peel a deref if the parent and child are both + // captured by-ref. This would be correct, except for the case where we have + // precise capturing projections, since the inserted deref is to the *beginning* + // and the peeled deref is at the *end*. I cannot seem to actually find a + // case where this happens, though, but let's keep this code flexible. - // Finally, store the type of the parent's captured place. We need - // this when building the field projection in the MIR body later on. - let mut parent_capture_ty = parent_capture.place.ty(); - parent_capture_ty = match parent_capture.info.capture_kind { - ty::UpvarCapture::ByValue => parent_capture_ty, - ty::UpvarCapture::ByRef(kind) => Ty::new_ref( - tcx, - tcx.lifetimes.re_erased, - parent_capture_ty, - kind.to_mutbl_lossy(), - ), - }; + // Finally, store the type of the parent's captured place. We need + // this when building the field projection in the MIR body later on. + let mut parent_capture_ty = parent_capture.place.ty(); + parent_capture_ty = match parent_capture.info.capture_kind { + ty::UpvarCapture::ByValue => parent_capture_ty, + ty::UpvarCapture::ByRef(kind) => Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + parent_capture_ty, + kind.to_mutbl_lossy(), + ), + }; + ( + FieldIdx::from_usize(child_field_idx + num_args), ( - FieldIdx::from_usize(child_field_idx + num_args), - ( - FieldIdx::from_usize(parent_field_idx + num_args), - parent_capture_ty, - peel_deref, - child_precise_captures, - ), - ) - }, - ) - .collect(); + FieldIdx::from_usize(parent_field_idx + num_args), + parent_capture_ty, + peel_deref, + child_precise_captures, + ), + ) + }, + ) + .collect(); - if coroutine_kind == ty::ClosureKind::FnOnce { - assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); - return; - } + if coroutine_kind == ty::ClosureKind::FnOnce { + assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); + // The by-move body is just the body :) + return coroutine_def_id.to_def_id(); + } - let by_move_coroutine_ty = tcx - .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) - .to_coroutine_given_kind_and_upvars( - tcx, - parent_closure_args.parent_args(), - coroutine_def_id.to_def_id(), - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - parent_closure_args.tupled_upvars_ty(), - parent_closure_args.coroutine_captures_by_ref_ty(), - ); + let by_move_coroutine_ty = tcx + .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) + .to_coroutine_given_kind_and_upvars( + tcx, + parent_closure_args.parent_args(), + coroutine_def_id.to_def_id(), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + parent_closure_args.tupled_upvars_ty(), + parent_closure_args.coroutine_captures_by_ref_ty(), + ); - let mut by_move_body = body.clone(); - MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); + let mut by_move_body = body.clone(); + MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); + dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); - // Let's just always validate this body. - validate_body(tcx, &mut by_move_body, "Initial coroutine_by_move body".to_string()); + let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody); + by_move_body.source = + mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); - // FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body. - by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim { - coroutine_def_id: coroutine_def_id.to_def_id(), - }); - body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); - } + // Inherited from the by-ref coroutine. + body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); + body_def.constness(tcx.constness(coroutine_def_id).clone()); + body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id).clone()); + body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id)); + body_def.def_span(tcx.def_span(coroutine_def_id)); + body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id).clone()); + body_def.generics_of(tcx.generics_of(coroutine_def_id).clone()); + body_def.param_env(tcx.param_env(coroutine_def_id).clone()); + body_def.predicates_of(tcx.predicates_of(coroutine_def_id).clone()); + + // The type of the coroutine is the `by_move_coroutine_ty`. + body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); + + body_def.mir_built(tcx.arena.alloc(Steal::new(by_move_body))); + + body_def.def_id().to_def_id() } struct MakeByMoveBody<'tcx> { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 96ca3b43d5c..af0f1e38a75 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,7 +13,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, @@ -159,7 +159,7 @@ fn create_mappings<'tcx>( .expect("all BCBs with spans were given counters") .as_term() }; - let region_for_span = |span: Span| make_code_region(source_map, file_name, span, body_span); + let region_for_span = |span: Span| make_source_region(source_map, file_name, span, body_span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -175,9 +175,9 @@ fn create_mappings<'tcx>( mappings.extend(code_mappings.iter().filter_map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -186,29 +186,29 @@ fn create_mappings<'tcx>( let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - let code_region = region_for_span(span)?; - Some(Mapping { kind, code_region }) + let source_region = region_for_span(span)?; + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_branches.iter().filter_map( |&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = match condition_info { Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params }, None => MappingKind::Branch { true_term, false_term }, }; - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_decisions.iter().filter_map( |&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions }); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -362,19 +362,13 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -fn make_code_region( +#[instrument(level = "debug", skip(source_map))] +fn make_source_region( source_map: &SourceMap, file_name: Symbol, span: Span, body_span: Span, -) -> Option<CodeRegion> { - debug!( - "Called make_code_region(file_name={}, span={}, body_span={})", - file_name, - source_map.span_to_diagnostic_string(span), - source_map.span_to_diagnostic_string(body_span) - ); - +) -> Option<SourceRegion> { let lo = span.lo(); let hi = span.hi(); @@ -424,7 +418,7 @@ fn make_code_region( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - check_code_region(CodeRegion { + check_source_region(SourceRegion { file_name, start_line: start_line as u32, start_col: start_col as u32, @@ -433,12 +427,12 @@ fn make_code_region( }) } -/// If `llvm-cov` sees a code region that is improperly ordered (end < start), +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. -fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> { - let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; +fn check_source_region(source_region: SourceRegion) -> Option<SourceRegion> { + let SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = source_region; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. @@ -451,17 +445,17 @@ fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> { let is_ordered = (start_line, start_col) <= (end_line, end_col); if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(code_region) + Some(source_region) } else { debug!( - ?code_region, + ?source_region, ?all_nonzero, ?end_col_has_high_bit_unset, ?is_ordered, - "Skipping code region that would be misinterpreted or rejected by LLVM" + "Skipping source region that would be misinterpreted or rejected by LLVM" ); // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper code region: {code_region:?}"); + debug_assert!(false, "Improper source region: {source_region:?}"); None } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 61fc5fc8816..2d6950be55d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -341,7 +341,6 @@ impl<'tcx> Inliner<'tcx> { | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index f5274c664cf..56e8905bead 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,7 +88,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::ThreadLocalShim { .. } | InstanceKind::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 1f214bc42cb..88094b44edf 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -135,6 +135,7 @@ pub fn provide(providers: &mut Providers) { mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, deduced_param_attrs: deduce_param_attrs::deduced_param_attrs, + coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id, ..providers.queries }; } @@ -293,10 +294,6 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), - // If this is an async closure's output coroutine, generate - // by-move and by-mut bodies if needed. We do this first so - // they can be optimized in lockstep with their parent bodies. - &coroutine::ByMoveBody, // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &rustc_peek::SanityCheck, // Just a lint @@ -329,8 +326,15 @@ fn mir_promoted( | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), }; - // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + + // the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run. tcx.ensure_with_value().has_ffi_unwind_calls(def); + + // the `by_move_body` query uses the raw mir, so make sure it is run. + if tcx.needs_coroutine_by_move_body_def_id(def) { + tcx.ensure_with_value().coroutine_by_move_body_def_id(def); + } + let mut body = tcx.mir_built(def).steal(); if let Some(error_reported) = const_qualifs.tainted_by_errors { body.tainted_by_errors = Some(error_reported); @@ -339,14 +343,6 @@ fn mir_promoted( // Collect `required_consts` *before* promotion, so if there are any consts being promoted // we still add them to the list in the outer MIR body. RequiredConstsVisitor::compute_required_consts(&mut body); - // If this has an associated by-move async closure body, that doesn't get run through these - // passes itself, it gets "tagged along" by the pass manager. `RequiredConstsVisitor` is not - // a regular pass so we have to also apply it manually to the other body. - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - RequiredConstsVisitor::compute_required_consts(by_move_body); - } - } // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); @@ -398,7 +394,10 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & if tcx.is_coroutine(def.to_def_id()) { tcx.ensure_with_value().mir_coroutine_witnesses(def); } - let mir_borrowck = tcx.mir_borrowck(def); + + // We only need to borrowck non-synthetic MIR. + let tainted_by_errors = + if !tcx.is_synthetic_mir(def) { tcx.mir_borrowck(def).tainted_by_errors } else { None }; let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { @@ -410,7 +409,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); - if let Some(error_reported) = mir_borrowck.tainted_by_errors { + + if let Some(error_reported) = tainted_by_errors { body.tainted_by_errors = Some(error_reported); } @@ -660,14 +660,6 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { // visited does not depend on the optimization level. // We do not use `run_passes` for this as that might skip the pass if `injection_phase` is set. mentioned_items::MentionedItems.run_pass(tcx, &mut body); - // If this has an associated by-move async closure body, that doesn't get run through these - // passes itself, it gets "tagged along" by the pass manager. Since we're not using the pass - // manager we have to do this by hand. - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - mentioned_items::MentionedItems.run_pass(tcx, by_move_body); - } - } // If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable // predicates, it will shrink the MIR to a single `unreachable` terminator. @@ -690,7 +682,9 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_ return tcx.arena.alloc(IndexVec::new()); } - tcx.ensure_with_value().mir_borrowck(def); + if !tcx.is_synthetic_mir(def) { + tcx.ensure_with_value().mir_borrowck(def); + } let mut promoted = tcx.mir_promoted(def).1.steal(); for body in &mut promoted { diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 824a4b2f2df..d092477e340 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -182,12 +182,6 @@ fn run_passes_inner<'tcx>( body.pass_count = 1; } - - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); - } - } } pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 09b4e5e0711..86eada0183f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -78,15 +78,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< receiver_by_ref, } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref), - ty::InstanceKind::CoroutineKindShim { coroutine_def_id } => { - return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone(); - } - ty::InstanceKind::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? - if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { - let coroutine_body = tcx.optimized_mir(*coroutine_def_id); + if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { + let coroutine_body = tcx.optimized_mir(coroutine_def_id); let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() else { @@ -105,7 +101,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), ty::ClosureKind::FnOnce ); - coroutine_body.coroutine_by_move_body().unwrap().coroutine_drop().unwrap() + tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id)) + .coroutine_drop() + .unwrap() }; let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 36908036796..99e06f59dd0 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -102,25 +102,6 @@ impl<'tcx> MirPass<'tcx> for Validator { } } } - - // Enforce that coroutine-closure layouts are identical. - if let Some(layout) = body.coroutine_layout_raw() - && let Some(by_move_body) = body.coroutine_by_move_body() - && let Some(by_move_layout) = by_move_body.coroutine_layout_raw() - { - // FIXME(async_closures): We could do other validation here? - if layout.variant_fields.len() != by_move_layout.variant_fields.len() { - cfg_checker.fail( - Location::START, - format!( - "Coroutine layout has different number of variant fields from \ - by-move coroutine layout:\n\ - layout: {layout:#?}\n\ - by_move_layout: {by_move_layout:#?}", - ), - ); - } - } } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 77f6a1e17ce..36fb2e89af1 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -920,7 +920,6 @@ fn visit_instance_use<'tcx>( | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Item(..) | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::CloneShim(..) @@ -1035,9 +1034,9 @@ fn find_vtable_types_for_unsizing<'tcx>( } }; - match (&source_ty.kind(), &target_ty.kind()) { + match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) - | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(*a, *b), + | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 610ad41ce52..2f0088fb34f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -626,7 +626,6 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::Virtual(..) @@ -796,7 +795,6 @@ fn mono_item_visibility<'tcx>( | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 5a24202db65..b59c7bcffa9 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -127,7 +127,7 @@ fn mark_used_by_default_parameters<'tcx>( unused_parameters: &mut UnusedGenericParams, ) { match tcx.def_kind(def_id) { - DefKind::Closure => { + DefKind::Closure | DefKind::SyntheticCoroutineBody => { for param in &generics.own_params { debug!(?param, "(closure/gen)"); unused_parameters.mark_used(param.index); diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 5738173c7a8..c7a9846cd97 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -862,7 +862,7 @@ where _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { - panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) + panic!("`TransmuteFrom` does not have an associated type: {:?}", goal) } fn consider_builtin_effects_intersection_candidate( diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 6391ff901cb..c65cf3f40f6 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -76,6 +76,7 @@ impl<'a> Parser<'a> { token::CommentKind::Line => OuterAttributeType::DocComment, token::CommentKind::Block => OuterAttributeType::DocBlockComment, }, + true, ) { err.note(fluent::parse_note); err.span_suggestion_verbose( @@ -139,7 +140,11 @@ impl<'a> Parser<'a> { // Emit error if inner attribute is encountered and forbidden. if style == ast::AttrStyle::Inner { - this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy); + this.error_on_forbidden_inner_attr( + attr_sp, + inner_parse_policy, + item.is_valid_for_outer_style(), + ); } Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp)) @@ -151,6 +156,7 @@ impl<'a> Parser<'a> { err: &mut Diag<'_>, span: Span, attr_type: OuterAttributeType, + suggest_to_outer: bool, ) -> Option<Span> { let mut snapshot = self.create_snapshot_for_diagnostic(); let lo = span.lo() @@ -185,16 +191,18 @@ impl<'a> Parser<'a> { // FIXME(#100717) err.arg("item", item.kind.descr()); err.span_label(item.span, fluent::parse_label_does_not_annotate_this); - err.span_suggestion_verbose( - replacement_span, - fluent::parse_sugg_change_inner_to_outer, - match attr_type { - OuterAttributeType::Attribute => "", - OuterAttributeType::DocBlockComment => "*", - OuterAttributeType::DocComment => "/", - }, - rustc_errors::Applicability::MachineApplicable, - ); + if suggest_to_outer { + err.span_suggestion_verbose( + replacement_span, + fluent::parse_sugg_change_inner_to_outer, + match attr_type { + OuterAttributeType::Attribute => "", + OuterAttributeType::DocBlockComment => "*", + OuterAttributeType::DocComment => "/", + }, + rustc_errors::Applicability::MachineApplicable, + ); + } return None; } Err(item_err) => { @@ -205,7 +213,12 @@ impl<'a> Parser<'a> { Some(replacement_span) } - pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy) { + pub(super) fn error_on_forbidden_inner_attr( + &self, + attr_sp: Span, + policy: InnerAttrPolicy, + suggest_to_outer: bool, + ) { if let InnerAttrPolicy::Forbidden(reason) = policy { let mut diag = match reason.as_ref().copied() { Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => { @@ -239,6 +252,7 @@ impl<'a> Parser<'a> { &mut diag, attr_sp, OuterAttributeType::Attribute, + suggest_to_outer, ) .is_some() { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 14da6c331f1..c6a5e1908f7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -51,7 +51,9 @@ impl<'a> Parser<'a> { } /// Parses the contents of a module (inner attributes followed by module items). - /// We exit once we hit `term` + /// We exit once we hit `term` which can be either + /// - EOF (for files) + /// - `}` for mod items pub fn parse_mod( &mut self, term: &TokenKind, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 69044192780..26ad39e06cd 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -459,11 +459,16 @@ impl<'a> Parser<'a> { pub fn parse_block(&mut self) -> PResult<'a, P<Block>> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { + let suggest_to_outer = match &last.kind { + ast::AttrKind::Normal(attr) => attr.item.is_valid_for_outer_style(), + _ => false, + }; self.error_on_forbidden_inner_attr( last.span, super::attr::InnerAttrPolicy::Forbidden(Some( InnerAttrForbiddenReason::InCodeBlock, )), + suggest_to_outer, ); } Ok(block) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index dfc726efeb9..38450fc288a 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -481,10 +481,6 @@ passes_must_not_suspend = `must_not_suspend` attribute should be applied to a struct, enum, union, or trait .label = is not a struct, enum, union, or trait -passes_must_use_async = - `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within - .label = this attribute does nothing, the `Future`s returned by async functions are already `must_use` - passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} @@ -657,6 +653,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_pub_transparent = + attribute should be applied to `#[repr(transparent)]` types + .label = not a `#[repr(transparent)]` type + passes_rustc_safe_intrinsic = attribute should be applied to intrinsic functions .label = not an intrinsic function @@ -672,6 +672,10 @@ passes_should_be_applied_to_fn = *[false] not a function definition } +passes_should_be_applied_to_fn_or_unit_struct = + attribute should be applied to a function definition or unit struct + .label = not a function definition or a unit struct + passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c93fb5c23b1..5dbb3854c8f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -245,6 +245,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_coroutine(attr, target); } [sym::linkage, ..] => self.check_linkage(attr, span, target), + [sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs), [ // ok sym::allow @@ -516,6 +517,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::no_mangle, sym::naked, sym::instruction_set, + sym::repr, // code generation sym::cold, sym::target_feature, @@ -745,12 +747,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); } + Target::Struct if self.tcx.features().struct_target_features => { + let ty = self.tcx.hir_node(hir_id).expect_item(); + match ty.kind { + ItemKind::Struct(data, _) => { + if data.fields().len() != 0 { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } + } + _ => { + panic!("Target::Struct for a non-struct"); + } + } + } _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); + if self.tcx.features().struct_target_features { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } else { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); + } } } } @@ -951,6 +976,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { bare_fn_ty.decl.inputs.len() == 1 } else { false + } + || if let Some(&[hir::GenericArg::Type(ty)]) = i + .of_trait + .as_ref() + .and_then(|trait_ref| trait_ref.path.segments.last()) + .map(|last_segment| last_segment.args().args) + { + matches!(&ty.kind, hir::TyKind::Tup([_])) + } else { + false }; if !is_valid { self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() }); @@ -2381,6 +2416,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } + + fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { + if !attrs + .iter() + .filter(|attr| attr.has_name(sym::repr)) + .filter_map(|attr| attr.meta_item_list()) + .flatten() + .any(|nmi| nmi.has_name(sym::transparent)) + { + self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1190e60f41f..32db0823cf7 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -83,6 +83,15 @@ pub struct AttrShouldBeAppliedToFn { } #[derive(Diagnostic)] +#[diag(passes_should_be_applied_to_fn_or_unit_struct)] +pub struct AttrShouldBeAppliedToFnOrUnitStruct { + #[primary_span] + pub attr_span: Span, + #[label] + pub defn_span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] pub struct TrackedCallerWrongLocation { #[primary_span] @@ -372,13 +381,6 @@ pub struct FfiConstInvalidTarget { } #[derive(LintDiagnostic)] -#[diag(passes_must_use_async)] -pub struct MustUseAsync { - #[label] - pub span: Span, -} - -#[derive(LintDiagnostic)] #[diag(passes_must_use_no_effect)] pub struct MustUseNoEffect { pub article: &'static str, @@ -623,6 +625,15 @@ pub struct RustcStdInternalSymbol { } #[derive(Diagnostic)] +#[diag(passes_rustc_pub_transparent)] +pub struct RustcPubTransparent { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_link_ordinal)] pub struct LinkOrdinal { #[primary_span] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d1d1e5e901f..9f78215bfd1 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -626,7 +626,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::Field | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::Closure => (), + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => (), } } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index fee42ba87c9..3ea782b62f1 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -197,8 +197,78 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) { for child in self.tcx.module_children(module.def_id()) { let parent_scope = ParentScope::module(module, self); - BuildReducedGraphVisitor { r: self, parent_scope } - .build_reduced_graph_for_external_crate_res(child); + self.build_reduced_graph_for_external_crate_res(child, parent_scope) + } + } + + /// Builds the reduced graph for a single item in an external crate. + fn build_reduced_graph_for_external_crate_res( + &mut self, + child: &ModChild, + parent_scope: ParentScope<'a>, + ) { + let parent = parent_scope.module; + let ModChild { ident, res, vis, ref reexport_chain } = *child; + let span = self.def_span( + reexport_chain + .first() + .and_then(|reexport| reexport.id()) + .unwrap_or_else(|| res.def_id()), + ); + let res = res.expect_non_local(); + let expansion = parent_scope.expansion; + // Record primary definitions. + match res { + Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => { + let module = self.expect_module(def_id); + self.define(parent, ident, TypeNS, (module, vis, span, expansion)); + } + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Variant + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::OpaqueTy + | DefKind::TraitAlias + | DefKind::AssocTy, + _, + ) + | Res::PrimTy(..) + | Res::ToolMod => self.define(parent, ident, TypeNS, (res, vis, span, expansion)), + Res::Def( + DefKind::Fn + | DefKind::AssocFn + | DefKind::Static { .. } + | DefKind::Const + | DefKind::AssocConst + | DefKind::Ctor(..), + _, + ) => self.define(parent, ident, ValueNS, (res, vis, span, expansion)), + Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { + self.define(parent, ident, MacroNS, (res, vis, span, expansion)) + } + Res::Def( + DefKind::TyParam + | DefKind::ConstParam + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Closure + | DefKind::SyntheticCoroutineBody + | DefKind::Impl { .. }, + _, + ) + | Res::Local(..) + | Res::SelfTyParam { .. } + | Res::SelfTyAlias { .. } + | Res::SelfCtor(..) + | Res::Err => bug!("unexpected resolution: {:?}", res), } } } @@ -967,72 +1037,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: &ModChild) { - let parent = self.parent_scope.module; - let ModChild { ident, res, vis, ref reexport_chain } = *child; - let span = self.r.def_span( - reexport_chain - .first() - .and_then(|reexport| reexport.id()) - .unwrap_or_else(|| res.def_id()), - ); - let res = res.expect_non_local(); - let expansion = self.parent_scope.expansion; - // Record primary definitions. - match res { - Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => { - let module = self.r.expect_module(def_id); - self.r.define(parent, ident, TypeNS, (module, vis, span, expansion)); - } - Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Variant - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::OpaqueTy - | DefKind::TraitAlias - | DefKind::AssocTy, - _, - ) - | Res::PrimTy(..) - | Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)), - Res::Def( - DefKind::Fn - | DefKind::AssocFn - | DefKind::Static { .. } - | DefKind::Const - | DefKind::AssocConst - | DefKind::Ctor(..), - _, - ) => self.r.define(parent, ident, ValueNS, (res, vis, span, expansion)), - Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.r.define(parent, ident, MacroNS, (res, vis, span, expansion)) - } - Res::Def( - DefKind::TyParam - | DefKind::ConstParam - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::Closure - | DefKind::Impl { .. }, - _, - ) - | Res::Local(..) - | Res::SelfTyParam { .. } - | Res::SelfTyAlias { .. } - | Res::SelfCtor(..) - | Res::Err => bug!("unexpected resolution: {:?}", res), - } - } - fn add_macro_use_binding( &mut self, name: Symbol, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ed23870dfdf..3595db78e93 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -314,13 +314,15 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - // HACK(min_generic_const_args): don't create defs for anon consts if we think they will - // later be turned into ConstArgKind::Path's. because this is before resolve is done, we - // may accidentally identify a construction of a unit struct as a param and not create a - // def. we'll then create a def later in ast lowering in this case. the parent of nested - // items will be messed up, but that's ok because there can't be any if we're just looking - // for bare idents. - if constant.value.is_potential_trivial_const_arg() { + if self.resolver.tcx.features().const_arg_path + && constant.value.is_potential_trivial_const_arg() + { + // HACK(min_generic_const_args): don't create defs for anon consts if we think they will + // later be turned into ConstArgKind::Path's. because this is before resolve is done, we + // may accidentally identify a construction of a unit struct as a param and not create a + // def. we'll then create a def later in ast lowering in this case. the parent of nested + // items will be messed up, but that's ok because there can't be any if we're just looking + // for bare idents. visit::walk_anon_const(self, constant) } else { let def = diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b84280a3ccf..01c371ee498 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -14,6 +14,10 @@ session_crate_name_empty = crate name must not be empty session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen +session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version} + +session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled + session_expr_parentheses_needed = parentheses are required to parse this as an expression session_failed_to_create_profiler = failed to create profiler: {$err} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 95d171409d8..4fb3702b05d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2893,6 +2893,7 @@ pub enum PpHirMode { } #[derive(Copy, Clone, PartialEq, Debug)] +/// Pretty print mode pub enum PpMode { /// Options that print the source code, i.e. /// `-Zunpretty=normal` and `-Zunpretty=expanded` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 5cc54a5855b..15bbd4ff7bf 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -166,6 +166,16 @@ pub(crate) struct UnsupportedDwarfVersion { } #[derive(Diagnostic)] +#[diag(session_embed_source_insufficient_dwarf_version)] +pub(crate) struct EmbedSourceInsufficientDwarfVersion { + pub(crate) dwarf_version: u32, +} + +#[derive(Diagnostic)] +#[diag(session_embed_source_requires_debug_info)] +pub(crate) struct EmbedSourceRequiresDebugInfo; + +#[derive(Diagnostic)] #[diag(session_target_stack_protector_not_supported)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) stack_protector: StackProtector, diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 63ca5fefd9f..d78f4a78de7 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -5,14 +5,11 @@ use std::{env, fs}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use smallvec::{smallvec, SmallVec}; -use tracing::debug; use crate::search_paths::{PathKind, SearchPath}; #[derive(Clone)] pub struct FileSearch<'a> { - sysroot: &'a Path, - triple: &'a str, cli_search_paths: &'a [SearchPath], tlib_path: &'a SearchPath, kind: PathKind, @@ -32,23 +29,12 @@ impl<'a> FileSearch<'a> { .chain(std::iter::once(self.tlib_path)) } - pub fn get_lib_path(&self) -> PathBuf { - make_target_lib_path(self.sysroot, self.triple) - } - - pub fn get_self_contained_lib_path(&self) -> PathBuf { - self.get_lib_path().join("self-contained") - } - pub fn new( - sysroot: &'a Path, - triple: &'a str, cli_search_paths: &'a [SearchPath], tlib_path: &'a SearchPath, kind: PathKind, ) -> FileSearch<'a> { - debug!("using sysroot = {}, triple = {}", sysroot.display(), triple); - FileSearch { sysroot, triple, cli_search_paths, tlib_path, kind } + FileSearch { cli_search_paths, tlib_path, kind } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index df72e2430fd..23231fbffbf 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1701,6 +1701,8 @@ options! { them only if an error has not been emitted"), ehcont_guard: bool = (false, parse_bool, [TRACKED], "generate Windows EHCont Guard tables"), + embed_source: bool = (false, parse_bool, [TRACKED], + "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), emit_thin_lto: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 693867c3853..70430d82ab5 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -37,8 +37,9 @@ use rustc_target::spec::{ use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use crate::config::{ - self, CoverageLevel, CrateType, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage, - OptLevel, OutFileName, OutputType, RemapPathScopeComponents, SwitchWithOptPath, + self, CoverageLevel, CrateType, DebugInfo, ErrorOutputType, FunctionReturn, Input, + InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents, + SwitchWithOptPath, }; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -439,22 +440,10 @@ impl Session { } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { - filesearch::FileSearch::new( - &self.sysroot, - self.opts.target_triple.triple(), - &self.opts.search_paths, - &self.target_tlib_path, - kind, - ) + filesearch::FileSearch::new(&self.opts.search_paths, &self.target_tlib_path, kind) } pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { - filesearch::FileSearch::new( - &self.sysroot, - config::host_triple(), - &self.opts.search_paths, - &self.host_tlib_path, - kind, - ) + filesearch::FileSearch::new(&self.opts.search_paths, &self.host_tlib_path, kind) } /// Returns a list of directories where target-specific tool binaries are located. Some fallback @@ -1306,6 +1295,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) { .emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } + if sess.opts.unstable_opts.embed_source { + let dwarf_version = + sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); + + if dwarf_version < 5 { + sess.dcx().emit_warn(errors::EmbedSourceInsufficientDwarfVersion { dwarf_version }); + } + + if sess.opts.debuginfo == DebugInfo::None { + sess.dcx().emit_warn(errors::EmbedSourceRequiresDebugInfo); + } + } + if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray { sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() }); } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 332fe22d869..9afd732486c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -851,7 +851,6 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceKind::FnPtrAddrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::ThreadLocalShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 41e9698242b..9b27b94fb5a 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -114,7 +114,9 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { | DefKind::GlobalAsm => { unreachable!("Not a valid item kind: {kind:?}"); } - DefKind::Closure | DefKind::AssocFn | DefKind::Fn => ItemKind::Fn, + DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => { + ItemKind::Fn + } DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { ItemKind::Const } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 434df35a515..5e1b1b44bc2 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1415,6 +1415,14 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext // Overwrite the dummy data with our decoded SyntaxContextData HygieneData::with(|hygiene_data| { + if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize) + && old.outer_expn == ctxt_data.outer_expn + && old.outer_transparency == ctxt_data.outer_transparency + && old.parent == ctxt_data.parent + { + ctxt_data = old.clone(); + } + let dummy = std::mem::replace( &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize], ctxt_data, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2e94492f8c..aba56732725 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -356,6 +356,7 @@ symbols! { _task_context, a32, aarch64_target_feature, + aarch64_unstable_target_feature, aarch64_ver_target_feature, abi, abi_amdgpu_kernel, @@ -595,6 +596,7 @@ symbols! { conservative_impl_trait, console, const_allocate, + const_arg_path, const_async_blocks, const_closures, const_compare_raw_pointers, @@ -673,6 +675,7 @@ symbols! { crate_visibility_modifier, crt_dash_static: "crt-static", csky_target_feature, + cstr_type, cstring_type, ctlz, ctlz_nonzero, @@ -1672,6 +1675,7 @@ symbols! { rustc_private, rustc_proc_macro_decls, rustc_promotable, + rustc_pub_transparent, rustc_reallocator, rustc_regions, rustc_reservation_impl, @@ -1849,6 +1853,7 @@ symbols! { stringify, struct_field_attributes, struct_inherit, + struct_target_features, struct_variant, structural_match, structural_peq, @@ -1893,6 +1898,7 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, tmm_reg, to_owned_method, to_string, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0f91684a3a4..59ccd6dff85 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -92,9 +92,6 @@ pub(super) fn mangle<'tcx>( .write_str(if receiver_by_ref { "{{by-move-shim}}" } else { "{{by-ref-shim}}" }) .unwrap(); } - ty::InstanceKind::CoroutineKindShim { .. } => { - printer.write_str("{{by-move-body-shim}}").unwrap(); - } _ => {} } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 3a606f244e3..75f4499352b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -56,7 +56,6 @@ pub(super) fn mangle<'tcx>( ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref: false, .. } => { Some("by_ref") } - ty::InstanceKind::CoroutineKindShim { .. } => Some("by_move_body"), _ => None, }; diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index c1ddfcb2f90..082c169b210 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -745,10 +745,25 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// Checks if these two `ArgAbi` are equal enough to be considered "the same for all /// function call ABIs". - pub fn eq_abi(&self, other: &Self) -> bool { + pub fn eq_abi(&self, other: &Self) -> bool + where + Ty: PartialEq, + { // Ideally we'd just compare the `mode`, but that is not enough -- for some modes LLVM will look // at the type. - self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) + self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) && { + // `fn_arg_sanity_check` accepts `PassMode::Direct` for some aggregates. + // That elevates any type difference to an ABI difference since we just use the + // full Rust type as the LLVM argument/return type. + if matches!(self.mode, PassMode::Direct(..)) + && matches!(self.layout.abi, Abi::Aggregate { .. }) + { + // For aggregates in `Direct` mode to be compatible, the types need to be equal. + self.layout.ty == other.layout.ty + } else { + true + } + } } } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 358efb4174d..daf5162e8ac 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -59,11 +59,11 @@ impl AArch64InlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<Symbol>)] { match self { - Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, + Self::reg => types! { _: I8, I16, I32, I64, F16, F32, F64; }, Self::vreg | Self::vreg_low16 => types! { - neon: I8, I16, I32, I64, F32, F64, - VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1), - VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); + neon: I8, I16, I32, I64, F16, F32, F64, F128, + VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), + VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); }, Self::preg => &[], } diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 0d61345a70e..cc383f88fbc 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -53,6 +53,8 @@ pub enum Abi { }, RustIntrinsic, RustCall, + /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even + /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! Unadjusted, /// For things unlikely to be called, where reducing register pressure in /// `extern "Rust"` callers is worth paying extra cost in the callee. diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 80f89a0ab2b..d5f227a84a4 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1750,6 +1750,9 @@ supported_targets! { ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl), + ("armv7-unknown-trusty", armv7_unknown_trusty), + ("aarch64-unknown-trusty", aarch64_unknown_trusty), + ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-risc0-zkvm-elf", riscv32im_risc0_zkvm_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs new file mode 100644 index 00000000000..1525faf9b7e --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -0,0 +1,34 @@ +// Trusty OS target for AArch64. + +use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "aarch64-unknown-unknown-musl".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARM64 Trusty".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+neon,+fp-armv8,+reserve-x18".into(), + executables: true, + max_atomic_width: Some(128), + panic_strategy: PanicStrategy::Abort, + os: "trusty".into(), + position_independent_executables: true, + static_position_independent_executables: true, + crt_static_default: true, + crt_static_respected: true, + dynamic_linking: false, + link_self_contained: LinkSelfContainedDefault::InferredForMusl, + relro_level: RelroLevel::Full, + mcount: "\u{1}_mcount".into(), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs new file mode 100644 index 00000000000..ae73de5e64d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -0,0 +1,37 @@ +use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it + // to determine the calling convention and float ABI, and it doesn't + // support the "musleabi" value. + llvm_target: "armv7-unknown-unknown-gnueabi".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Armv7-A Trusty".into()), + tier: Some(2), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + options: TargetOptions { + abi: "eabi".into(), + features: "+v7,+thumb2,+soft-float,-neon".into(), + max_atomic_width: Some(64), + mcount: "\u{1}mcount".into(), + os: "trusty".into(), + link_self_contained: LinkSelfContainedDefault::InferredForMusl, + dynamic_linking: false, + executables: true, + crt_static_default: true, + crt_static_respected: true, + relro_level: RelroLevel::Full, + panic_strategy: PanicStrategy::Abort, + position_independent_executables: true, + static_position_independent_executables: true, + + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index da66ba270b3..8319cb880cc 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -99,6 +99,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("bti", Stable, &[]), // FEAT_CRC ("crc", Stable, &[]), + // FEAT_CSSC + ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_DIT ("dit", Stable, &[]), // FEAT_DotProd @@ -107,21 +109,37 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("dpb", Stable, &[]), // FEAT_DPB2 ("dpb2", Stable, &["dpb"]), + // FEAT_ECV + ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_F32MM ("f32mm", Stable, &["sve"]), // FEAT_F64MM ("f64mm", Stable, &["sve"]), + // FEAT_FAMINMAX + ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FCMA ("fcma", Stable, &["neon"]), // FEAT_FHM ("fhm", Stable, &["fp16"]), // FEAT_FLAGM ("flagm", Stable, &[]), + // FEAT_FLAGM2 + ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 ("fp16", Stable, &["neon"]), + // FEAT_FP8 + ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + // FEAT_FP8DOT2 + ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + // FEAT_FP8DOT4 + ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + // FEAT_FP8FMA + ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), // FEAT_FRINTTS ("frintts", Stable, &[]), + // FEAT_HBC + ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_I8MM ("i8mm", Stable, &[]), // FEAT_JSCVT @@ -131,6 +149,14 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lor", Stable, &[]), // FEAT_LSE ("lse", Stable, &[]), + // FEAT_LSE128 + ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + // FEAT_LSE2 + ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_LUT + ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MOPS + ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MTE & FEAT_MTE2 ("mte", Stable, &[]), // FEAT_AdvSimd & FEAT_FP @@ -143,14 +169,16 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("pan", Stable, &[]), // FEAT_PMUv3 ("pmuv3", Stable, &[]), - // FEAT_RAND + // FEAT_RNG ("rand", Stable, &[]), // FEAT_RAS & FEAT_RASv1p1 ("ras", Stable, &[]), - // FEAT_RCPC + // FEAT_LRCPC ("rcpc", Stable, &[]), - // FEAT_RCPC2 + // FEAT_LRCPC2 ("rcpc2", Stable, &["rcpc"]), + // FEAT_LRCPC3 + ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), // FEAT_SB @@ -161,10 +189,36 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha3", Stable, &["sha2"]), // FEAT_SM3 & FEAT_SM4 ("sm4", Stable, &["neon"]), + // FEAT_SME + ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_F16F16 + ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SME_F64F64 + ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_F8F16 + ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + // FEAT_SME_F8F32 + ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SME_FA64 + ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + // FEAT_SME_I16I64 + ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_LUTv2 + ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_SME2 + ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME2p1 + ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SPE ("spe", Stable, &[]), // FEAT_SSBS & FEAT_SSBS2 ("ssbs", Stable, &[]), + // FEAT_SSVE_FP8FDOT2 + ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + // FEAT_SSVE_FP8FDOT4 + ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + // FEAT_SSVE_FP8FMA + ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SVE // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 // @@ -173,9 +227,11 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), + // FEAT_SVE_B16B16 (SVE or SME Instructions) + ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), - // FEAT_SVE2_AES + // FEAT_SVE_AES & FEAT_SVE_PMULL128 ("sve2-aes", Stable, &["sve2", "aes"]), // FEAT_SVE2_BitPerm ("sve2-bitperm", Stable, &["sve2"]), @@ -183,6 +239,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sve2-sha3", Stable, &["sve2", "sha3"]), // FEAT_SVE2_SM4 ("sve2-sm4", Stable, &["sve2", "sm4"]), + // FEAT_SVE2p1 + ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), // FEAT_TME ("tme", Stable, &[]), ( @@ -199,9 +257,19 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), // FEAT_VHE ("vh", Stable, &[]), + // FEAT_WFxT + ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 137850f31d3..3ddd23924b5 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point +trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 173671059ca..53f013ac153 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -384,6 +384,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: false, path: Default::default(), + time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -577,6 +578,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } + + let time_version = + self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); + match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -588,6 +593,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.is_some(), path: path.unwrap_or_default(), + time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -613,6 +619,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } + + /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. + /// <https://github.com/rust-lang/rust/issues/127343> + // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. + fn detect_old_time_crate_version( + &self, + span: Option<Span>, + kind: &InferSourceKind<'_>, + // We will clear the non-actionable suggestion from the error to reduce noise. + infer_subdiags: &mut Vec<SourceKindSubdiag<'_>>, + ) -> bool { + // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing + // compilation once we promote 1.89 to beta, which will happen in 9 months from now. + #[cfg(not(version("1.89")))] + const fn version_check() {} + #[cfg(version("1.89"))] + const fn version_check() { + panic!("remove this check as presumably the ecosystem has moved from needing it"); + } + const { version_check() }; + // Only relevant when building the `time` crate. + if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time + && let Some(span) = span + && let InferSourceKind::LetBinding { pattern_name, .. } = kind + && let Some(name) = pattern_name + && name.as_str() == "items" + && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) + { + let path = file.local_path_if_available().to_string_lossy(); + if path.contains("format_description") && path.contains("parse") { + infer_subdiags.clear(); + return true; + } + } + false + } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 3f35391be13..cd61747917a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // region at the right depth with the same index (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); - if id == def_id { + if id.to_def_id() == def_id { return ControlFlow::Break(arg); } } @@ -118,7 +118,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { debruijn_index ); debug!("LateBound id={:?} def_id={:?}", id, def_id); - if debruijn_index == self.current_index && id == def_id { + if debruijn_index == self.current_index && id.to_def_id() == def_id { return ControlFlow::Break(arg); } } @@ -192,7 +192,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { // the lifetime of the TyPath! (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); - if id == def_id { + if id.to_def_id() == def_id { return ControlFlow::Break(()); } } @@ -201,7 +201,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); - if debruijn_index == self.current_index && id == def_id { + if debruijn_index == self.current_index && id.to_def_id() == def_id { return ControlFlow::Break(()); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index 9c772f42cca..f2a7da707b8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -11,7 +11,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> { match &self.error { Some(RegionResolutionError::ConcreteFailure( - SubregionOrigin::RelateRegionParamBound(span), + SubregionOrigin::RelateRegionParamBound(span, _), Region(Interned( RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: sub_name, .. }, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs index 04e1be22a4d..600da730845 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } .add_to_diag(err); } @@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note, }) } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 877a8a23d7f..ada44b632d4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -257,7 +257,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err); } } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_region_param_bound, @@ -410,7 +410,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note, }) } - infer::RelateRegionParamBound(span) => { + infer::RelateRegionParamBound(span, ty) => { let param_instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, @@ -419,11 +419,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { note_and_explain::PrefixKind::LfParamInstantiatedWith, note_and_explain::SuffixKind::Empty, ); + let mut alt_span = None; + if let Some(ty) = ty + && sub.is_static() + && let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind() + && let Some(def_id) = preds.principal_def_id() + { + for (clause, span) in + self.tcx.predicates_of(def_id).instantiate_identity(self.tcx) + { + if let ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) = + clause.kind().skip_binder() + && let ty::Param(param) = a.kind() + && param.name == kw::SelfUpper + && b.is_static() + { + // Point at explicit `'static` bound on the trait (`trait T: 'static`). + alt_span = Some(span); + } + } + } let param_must_outlive = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, sub, - None, + alt_span, note_and_explain::PrefixKind::LfParamMustOutlive, note_and_explain::SuffixKind::Empty, ); @@ -1079,16 +1099,8 @@ fn msg_span_from_named_region<'tcx>( ) -> (String, Option<Span>) { match *region { ty::ReEarlyParam(br) => { - let scope = tcx - .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id) - .expect_local(); - let span = if let Some(param) = - tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) - { - param.span - } else { - tcx.def_span(scope) - }; + let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id; + let span = tcx.def_span(param_def_id); let text = if br.has_name() { format!("the lifetime `{}` as defined here", br.name) } else { @@ -1104,16 +1116,8 @@ fn msg_span_from_named_region<'tcx>( ("the anonymous lifetime defined here".to_string(), Some(ty.span)) } else { match fr.bound_region { - ty::BoundRegionKind::BrNamed(_, name) => { - let span = if let Some(param) = tcx - .hir() - .get_generics(generic_param_scope) - .and_then(|generics| generics.get_named(name)) - { - param.span - } else { - tcx.def_span(generic_param_scope) - }; + ty::BoundRegionKind::BrNamed(param_def_id, name) => { + let span = tcx.def_span(param_def_id); let text = if name == kw::UnderscoreLifetime { "the anonymous lifetime as defined here".to_string() } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 35f68a56d2d..ba656493d46 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -382,7 +382,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if !expected_inner.is_fn() || !found_inner.is_fn() { return; } - match (&expected_inner.kind(), &found_inner.kind()) { + match (expected_inner.kind(), found_inner.kind()) { (ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => { let sig = sig_tys.with(*hdr); let expected_sig = &(self.normalize_fn_sig)(sig); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d1cc630bc9a..def9d6e9a31 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -438,6 +438,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_target_feature_fn = if let ty::FnDef(def_id, _) = *leaf_trait_ref.skip_binder().self_ty().kind() { + // FIXME(struct_target_features): should a function that inherits + // target_features through arguments implement Fn traits? !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { false @@ -1693,7 +1695,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { StringPart::highlighted("multiple different versions".to_string()), StringPart::normal(" of crate `".to_string()), StringPart::highlighted(format!("{name}")), - StringPart::normal("` the your dependency graph".to_string()), + StringPart::normal("` in the dependency graph".to_string()), ], ); let candidates = if impl_candidates.is_empty() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index a962be54c3d..3cb95294fb6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2727,6 +2727,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let tcx = self.tcx; let predicate = predicate.upcast(tcx); + let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| { + if let Some(pred) = predicate.as_trait_clause() + && tcx.is_lang_item(pred.def_id(), LangItem::Sized) + && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind + { + err.span_suggestion_verbose( + expr.span.until(inner.span), + "references are always `Sized`, even if they point to unsized data; consider \ + not dereferencing the expression", + String::new(), + Applicability::MaybeIncorrect, + ); + } + }; match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } @@ -2773,6 +2787,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) if !span.is_dummy() => { + if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code { + if let Node::Expr(expr) = tcx.parent_hir_node(*hir_id) + && let hir::ExprKind::Call(_, args) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } else if let Node::Expr(expr) = self.tcx.hir_node(*hir_id) + && let hir::ExprKind::MethodCall(_, _, args, _) = expr.kind + && let Some(expr) = args.get(*pos) + { + suggest_remove_deref(err, &expr); + } + } let item_name = tcx.def_path_str(item_def_id); let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id)); let mut multispan = MultiSpan::from(span); @@ -2970,6 +2997,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )); err.downgrade_to_delayed_bug(); } + let mut local = true; match tcx.parent_hir_node(hir_id) { Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }) => { err.span_suggestion_verbose( @@ -2978,7 +3006,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); } Node::LetStmt(hir::LetStmt { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), @@ -2993,7 +3020,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); - err.note("all local variables must have a statically known size"); + } + Node::LetStmt(hir::LetStmt { init: Some(expr), .. }) => { + // When encountering an assignment of an unsized trait, like `let x = *"";`, + // we check if the RHS is a deref operation, to suggest removing it. + suggest_remove_deref(err, &expr); } Node::Param(param) => { err.span_suggestion_verbose( @@ -3003,10 +3034,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "&", Applicability::MachineApplicable, ); + local = false; } - _ => { - err.note("all local variables must have a statically known size"); - } + _ => {} + } + if local { + err.note("all local variables must have a statically known size"); } if !tcx.features().unsized_locals { err.help("unsized locals are gated as an unstable feature"); @@ -3529,14 +3562,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } ObligationCauseCode::OpaqueReturnType(expr_info) => { - if let Some((expr_ty, expr_span)) = expr_info { + if let Some((expr_ty, hir_id)) = expr_info { let expr_ty = self.tcx.short_ty_string(expr_ty, &mut long_ty_file); + let expr = self.infcx.tcx.hir().expect_expr(hir_id); err.span_label( - expr_span, + expr.span, with_forced_trimmed_paths!(format!( "return type was inferred to be `{expr_ty}` here", )), ); + suggest_remove_deref(err, &expr); } } } @@ -4667,10 +4702,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let hir::ExprKind::Block(b, _) = body.value.kind && b.expr.is_none() { + // The span of '}' in the end of block. + let span = self.tcx.sess.source_map().end_point(b.span); sugg_spans.push(( - // The span will point to the closing curly brace `}` of the block. - b.span.shrink_to_hi().with_lo(b.span.hi() - BytePos(1)), - "\n Ok(())\n}".to_string(), + span.shrink_to_lo(), + format!( + "{}{}", + " Ok(())\n", + self.tcx.sess.source_map().indentation_before(span).unwrap_or_default(), + ), )); } err.multipart_suggestion_verbose( diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5384084f6d7..ebaec0b9059 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -205,6 +205,8 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: bool, pub path: PathBuf, + #[note(trait_selection_type_annotations_needed_error_time)] + pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1bd66266936..c98d6c5f1df 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -19,6 +19,7 @@ #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] +#![feature(cfg_version)] #![feature(control_flow_enum)] #![feature(extract_if)] #![feature(if_let_guard)] diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cb8deeaedb6..a21feec4b1a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -545,6 +545,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). ty::FnDef(def_id, args) => { let tcx = self.tcx(); + // FIXME(struct_target_features): should a function that inherits target_features + // through an argument implement Fn traits? if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 7c73f74e629..2c67e7d4847 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -179,7 +179,7 @@ pub(crate) mod rustc { }; use super::Tree; - use crate::layout::rustc::{Def, Ref}; + use crate::layout::rustc::{layout_of, Def, Ref}; #[derive(Debug, Copy, Clone)] pub(crate) enum Err { @@ -206,7 +206,7 @@ pub(crate) mod rustc { impl<'tcx> Tree<Def<'tcx>, Ref<'tcx>> { pub fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, Err> { use rustc_target::abi::HasDataLayout; - let layout = ty_layout(cx, ty); + let layout = layout_of(cx, ty)?; if let Err(e) = ty.error_reported() { return Err(Err::TypeError(e)); @@ -239,7 +239,7 @@ pub(crate) mod rustc { let FieldsShape::Array { stride, count } = &layout.fields else { return Err(Err::NotYetSupported); }; - let inner_layout = ty_layout(cx, *inner_ty); + let inner_layout = layout_of(cx, *inner_ty)?; assert_eq!(*stride, inner_layout.size); let elt = Tree::from_ty(*inner_ty, cx)?; Ok(std::iter::repeat(elt) @@ -254,7 +254,7 @@ pub(crate) mod rustc { }, ty::Ref(lifetime, ty, mutability) => { - let layout = ty_layout(cx, *ty); + let layout = layout_of(cx, *ty)?; let align = layout.align.abi.bytes_usize(); let size = layout.size.bytes_usize(); Ok(Tree::Ref(Ref { @@ -280,7 +280,7 @@ pub(crate) mod rustc { FieldsShape::Primitive => { assert_eq!(members.len(), 1); let inner_ty = members[0]; - let inner_layout = ty_layout(cx, inner_ty); + let inner_layout = layout_of(cx, inner_ty)?; Self::from_ty(inner_ty, cx) } FieldsShape::Arbitrary { offsets, .. } => { @@ -413,7 +413,7 @@ pub(crate) mod rustc { let padding = Self::padding(padding_needed.bytes_usize()); let field_ty = ty_field(cx, (ty, layout), field_idx); - let field_layout = ty_layout(cx, field_ty); + let field_layout = layout_of(cx, field_ty)?; let field_tree = Self::from_ty(field_ty, cx)?; struct_tree = struct_tree.then(padding).then(field_tree); @@ -471,7 +471,7 @@ pub(crate) mod rustc { |fields, (idx, field_def)| { let field_def = Def::Field(field_def); let field_ty = ty_field(cx, (ty, layout), idx); - let field_layout = ty_layout(cx, field_ty); + let field_layout = layout_of(cx, field_ty)?; let field = Self::from_ty(field_ty, cx)?; let trailing_padding_needed = layout.size - field_layout.size; let trailing_padding = Self::padding(trailing_padding_needed.bytes_usize()); @@ -484,10 +484,6 @@ pub(crate) mod rustc { } } - pub(crate) fn ty_layout<'tcx>(cx: LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>) -> Layout<'tcx> { - crate::layout::rustc::layout_of(cx, ty).unwrap() - } - fn ty_field<'tcx>( cx: LayoutCx<'tcx, TyCtxt<'tcx>>, (ty, layout): (Ty<'tcx>, Layout<'tcx>), diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 1f3c4e3c817..2762b4e6384 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -44,18 +44,11 @@ mod rustc { let Self { src, dst, assume, context } = self; let layout_cx = LayoutCx { tcx: context, param_env: ParamEnv::reveal_all() }; - let layout_of = |ty| { - crate::layout::rustc::layout_of(layout_cx, ty) - .map_err(|_| Err::NotYetSupported) - .and_then(|_| Tree::from_ty(ty, layout_cx)) - }; // Convert `src` and `dst` from their rustc representations, to `Tree`-based - // representations. If these conversions fail, conclude that the transmutation is - // unacceptable; the layouts of both the source and destination types must be - // well-defined. - let src = layout_of(src); - let dst = layout_of(dst); + // representations. + let src = Tree::from_ty(src, layout_cx); + let dst = Tree::from_ty(dst, layout_cx); match (src, dst) { (Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => { diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs index 95373916a71..f8b59bdf326 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs @@ -4,7 +4,6 @@ use crate::layout; pub(crate) trait QueryContext { type Def: layout::Def; type Ref: layout::Ref; - type Scope: Copy; } #[cfg(test)] @@ -28,20 +27,17 @@ pub(crate) mod test { impl QueryContext for UltraMinimal { type Def = Def; type Ref = !; - type Scope = (); } } #[cfg(feature = "rustc")] mod rustc { - use rustc_middle::ty::{Ty, TyCtxt}; + use rustc_middle::ty::TyCtxt; use super::*; impl<'tcx> super::QueryContext for TyCtxt<'tcx> { type Def = layout::rustc::Def<'tcx>; type Ref = layout::rustc::Ref<'tcx>; - - type Scope = Ty<'tcx>; } } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 7e3c30f2383..16cd147b7d4 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -169,39 +169,6 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; - let mut ty = ty; - // When this `Closure` comes from a `CoroutineKindShim`, - // make sure we respect the `target_kind` in that shim. - // FIXME(async_closures): This shouldn't be needed, and we should be populating - // a separate def-id for these bodies. - if let InstanceKind::CoroutineKindShim { .. } = instance.def { - // Grab the parent coroutine-closure. It has the same args for the purposes - // of instantiation, so this will be okay to do. - let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx - .instantiate_and_normalize_erasing_regions( - args, - param_env, - tcx.type_of(tcx.parent(did)), - ) - .kind() - else { - bug!("CoroutineKindShim comes from calling a coroutine-closure"); - }; - let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); - ty = tcx.instantiate_bound_regions_with_erased( - coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { - sig.to_coroutine_given_kind_and_upvars( - tcx, - coroutine_closure_args.parent_args(), - did, - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - coroutine_closure_args.tupled_upvars_ty(), - coroutine_closure_args.coroutine_captures_by_ref_ty(), - ) - }), - ); - } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 8812260b3af..70321a071a2 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -144,7 +144,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Closure => ty::List::empty(), + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => ty::List::empty(), } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index c7ed6e6110f..d77c3a277bf 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -363,6 +363,11 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ), } + } else if tcx.is_lang_item(trait_ref.def_id, LangItem::TransmuteTrait) { + let name = tcx.item_name(trait_item_id); + assert_eq!(name, sym::transmute); + let args = tcx.erase_regions(rcvr_args); + Some(ty::Instance::new(trait_item_id, args)) } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d274a934d52..9a3956596d2 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -366,7 +366,7 @@ fn adt_consider_insignificant_dtor<'tcx>( fn adt_drop_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> { +) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> { // This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are // significant. let adt_has_dtor = diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 6680b451b7c..e899284674c 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -348,7 +348,8 @@ fn opaque_types_defined_by<'tcx>( | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm - | DefKind::Impl { .. } => {} + | DefKind::Impl { .. } + | DefKind::SyntheticCoroutineBody => {} // Closures and coroutines are type checked with their parent, so we need to allow all // opaques from the closure signature *and* from the parent body. DefKind::Closure | DefKind::InlineConst => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 568b9383ffb..6f1cbb0fee7 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -87,7 +87,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // These are not part of a public API, they can only appear as hidden types, and there // the interesting parts are solely in the signature of the containing item's opaque type // or dyn type. - DefKind::InlineConst | DefKind::Closure => {} + DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::Impl { of_trait } => { if of_trait { let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 2750838bbe9..98cc116bd00 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" bitflags = "2.4.1" derive-where = "1.2.7" indexmap = "2.0.0" +rustc-hash = "1.1.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } @@ -31,3 +32,6 @@ nightly = [ "rustc_index/nightly", "rustc_ast_ir/nightly" ] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] } diff --git a/compiler/rustc_type_ir/src/data_structures.rs b/compiler/rustc_type_ir/src/data_structures.rs index 4ca97c0c86c..96036e53b0a 100644 --- a/compiler/rustc_type_ir/src/data_structures.rs +++ b/compiler/rustc_type_ir/src/data_structures.rs @@ -1,8 +1,13 @@ +use std::hash::BuildHasherDefault; + +use rustc_hash::FxHasher; +pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; + +pub type IndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>; +pub type IndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>; + #[cfg(feature = "nightly")] mod impl_ { - pub use rustc_data_structures::fx::{ - FxHashMap as HashMap, FxHashSet as HashSet, FxIndexMap as IndexMap, FxIndexSet as IndexSet, - }; pub use rustc_data_structures::sso::{SsoHashMap, SsoHashSet}; pub use rustc_data_structures::stack::ensure_sufficient_stack; pub use rustc_data_structures::sync::Lrc; @@ -10,11 +15,9 @@ mod impl_ { #[cfg(not(feature = "nightly"))] mod impl_ { - pub use std::collections::{HashMap, HashMap as SsoHashMap, HashSet, HashSet as SsoHashSet}; + pub use std::collections::{HashMap as SsoHashMap, HashSet as SsoHashSet}; pub use std::sync::Arc as Lrc; - pub use indexmap::{IndexMap, IndexSet}; - #[inline] pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R { f() diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index f30419c801f..433c444e701 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -237,7 +237,7 @@ pub fn supertrait_def_ids<I: Interner>( cx: I, trait_def_id: I::DefId, ) -> impl Iterator<Item = I::DefId> { - let mut set = HashSet::default(); + let mut set: HashSet<I::DefId> = HashSet::default(); let mut stack = vec![trait_def_id]; set.insert(trait_def_id); diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index bfcea6a81d3..e8afaf1a480 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -68,6 +68,9 @@ struct OutlivesCollector<'a, I: Interner> { } impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> { + #[cfg(not(feature = "nightly"))] + type Result = (); + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { if !self.visited.insert(ty) { return; diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index d47c9e725f3..418139c3aad 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -287,7 +287,7 @@ impl<X: Cx> NestedGoals<X> { } } - #[rustc_lint_query_instability] + #[cfg_attr(feature = "nightly", rustc_lint_query_instability)] #[allow(rustc::potential_query_instability)] fn iter(&self) -> impl Iterator<Item = (X::Input, UsageKind)> + '_ { self.nested_goals.iter().map(|(i, p)| (*i, *p)) diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 50d7bae21db..aeae866e9d3 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -465,6 +465,22 @@ impl Location { } } +/// Location of the statement at the given index for a given basic block. Assumes that `stmt_idx` +/// and `bb_idx` are valid for a given body. +pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location { + let bb = &body.blocks[*bb_idx]; + let stmt = &bb.statements[stmt_idx]; + Location(stmt.span) +} + +/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given +/// body. +pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location { + let bb = &body.blocks[*bb_idx]; + let terminator = &bb.terminator; + Location(terminator.span) +} + /// Reference to a place used to represent a partial projection. pub struct PlaceRef<'a> { pub local: Local, diff --git a/config.example.toml b/config.example.toml index 1b7de662e84..f1dc32234cc 100644 --- a/config.example.toml +++ b/config.example.toml @@ -337,6 +337,7 @@ # "analysis", # "src", # "wasm-component-ld", +# "miri", "cargo-miri" # for dev/nightly channels #] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation diff --git a/library/Cargo.lock b/library/Cargo.lock index 30f5076e1e2..aa22181a463 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.118" +version = "0.1.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92afe7344b64cccf3662ca26d5d1c0828ab826f04206b97d856e3625e390e4b5" +checksum = "ce956e6dc07082ec481f0935a51e83b343f8ca51be560452c0ebf830d0bdf5a5" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index bdf16257c7c..a39a0a6ce0e 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.118", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.121", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7de41259599..caaf37f0465 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -293,6 +293,7 @@ impl<T> Box<T> { /// /// ``` /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// let zero = Box::<u32>::new_zeroed(); /// let zero = unsafe { zero.assume_init() }; @@ -303,7 +304,7 @@ impl<T> Box<T> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> { Self::new_zeroed_in(Global) @@ -684,6 +685,7 @@ impl<T> Box<[T]> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// let values = Box::<[u32]>::new_zeroed_slice(3); @@ -694,7 +696,7 @@ impl<T> Box<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> { unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } @@ -955,6 +957,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` + /// #![feature(box_uninit_write)] /// #![feature(new_uninit)] /// /// let big_box = Box::<[usize; 1024]>::new_uninit(); @@ -972,7 +975,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// assert_eq!(*x, i); /// } /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "box_uninit_write", issue = "129397")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box<T, A> { unsafe { @@ -1254,6 +1257,95 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { unsafe { (Unique::from(&mut *ptr), alloc) } } + /// Returns a raw mutable pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize references to the memory + /// may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut b = Box::new(0); + /// let ptr1 = Box::as_mut_ptr(&mut b); + /// ptr1.write(1); + /// let ptr2 = Box::as_mut_ptr(&mut b); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_mut_ptr(b: &mut Self) -> *mut T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of_mut!(**b) + } + + /// Returns a raw pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`]. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize mutable references to the memory, + /// as well as writing to this memory, may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut v = Box::new(0); + /// let ptr1 = Box::as_ptr(&v); + /// let ptr2 = Box::as_mut_ptr(&mut v); + /// let _val = ptr2.read(); + /// // No write to this memory has happened yet, so `ptr1` is still valid. + /// let _val = ptr1.read(); + /// // However, once we do a write... + /// ptr2.write(1); + /// // ... `ptr1` is no longer valid. + /// // This would be UB: let _val = ptr1.read(); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_ptr(b: &Self) -> *const T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of!(**b) + } + /// Returns a reference to the underlying allocator. /// /// Note: this is an associated function, which means that you have diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bdee06154fa..f153aa6d3be 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -539,6 +539,7 @@ impl<T> Rc<T> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::rc::Rc; @@ -551,7 +552,7 @@ impl<T> Rc<T> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> { unsafe { @@ -1000,6 +1001,7 @@ impl<T> Rc<[T]> { /// /// ``` /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; /// @@ -1011,7 +1013,7 @@ impl<T> Rc<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> { unsafe { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2c0d19b0ada..4a3522f1a64 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -542,6 +542,7 @@ impl<T> Arc<T> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::sync::Arc; @@ -555,7 +556,7 @@ impl<T> Arc<T> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> { unsafe { @@ -1134,6 +1135,7 @@ impl<T> Arc<[T]> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::sync::Arc; @@ -1147,7 +1149,7 @@ impl<T> Arc<[T]> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> { unsafe { @@ -1191,7 +1193,7 @@ impl<T, A: Allocator> Arc<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit<T>], A> { unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } @@ -1220,7 +1222,7 @@ impl<T, A: Allocator> Arc<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit<T>], A> { unsafe { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b4e0bc5fcbe..cfd2e4a1512 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1334,7 +1334,7 @@ impl<T, A: Allocator> Vec<T, A> { self.buf.ptr() } - /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling + /// Returns a raw mutable pointer to the vector's buffer, or a dangling /// raw pointer valid for zero sized reads if the vector didn't allocate. /// /// The caller must ensure that the vector outlives the pointer this @@ -1350,7 +1350,6 @@ impl<T, A: Allocator> Vec<T, A> { /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// - /// /// # Examples /// /// ``` diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index faee64b2f67..bfc31a626fa 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -59,6 +59,7 @@ fn box_deref_lval() { assert_eq!(x.get(), 1000); } +#[allow(unused)] pub struct ConstAllocator; unsafe impl Allocator for ConstAllocator { diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 375358dddf5..ce09a0b444d 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -3,8 +3,8 @@ //! suggestions from rustc if you get anything slightly wrong in here, and overall //! helps with clarity as we're also referring to `char` intentionally in here. -use crate::fmt; use crate::mem::transmute; +use crate::{assert_unsafe_precondition, fmt}; /// One of the 128 Unicode characters from U+0000 through U+007F, /// often known as the [ASCII] subset. @@ -497,14 +497,18 @@ impl AsciiChar { /// Notably, it should not be expected to return hex digits, or any other /// reasonable extension of the decimal digits. /// - /// (This lose safety condition is intended to simplify soundness proofs + /// (This loose safety condition is intended to simplify soundness proofs /// when writing code using this method, since the implementation doesn't /// need something really specific, not to make those other arguments do /// something useful. It might be tightened before stabilization.) #[unstable(feature = "ascii_char", issue = "110998")] #[inline] pub const unsafe fn digit_unchecked(d: u8) -> Self { - debug_assert!(d < 10); + assert_unsafe_precondition!( + check_language_ub, + "`AsciiChar::digit_unchecked` input cannot exceed 9.", + (d: u8 = d) => d < 10 + ); // SAFETY: `'0'` through `'9'` are U+00030 through U+0039, // so because `d` must be 64 or less the addition can return at most diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d860f3415d9..5dd9721d3fe 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -306,6 +306,7 @@ pub use once::OnceCell; /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct Cell<T: ?Sized> { value: UnsafeCell<T>, } @@ -2055,6 +2056,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct UnsafeCell<T: ?Sized> { value: T, } @@ -2297,6 +2299,7 @@ impl<T> UnsafeCell<*mut T> { /// See [`UnsafeCell`] for details. #[unstable(feature = "sync_unsafe_cell", issue = "95439")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct SyncUnsafeCell<T: ?Sized> { value: UnsafeCell<T>, } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 097fa86c938..87df8a4e272 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -309,7 +309,8 @@ impl<T> OnceCell<T> { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] - pub fn into_inner(self) -> Option<T> { + #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")] + pub const fn into_inner(self) -> Option<T> { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option<T>`. self.inner.into_inner() diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 6cc91849e1d..cac00b37d1f 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -1,9 +1,6 @@ #![doc = include_str!("error.md")] #![stable(feature = "error_in_core", since = "1.81.0")] -#[cfg(test)] -mod tests; - use crate::any::TypeId; use crate::fmt::{Debug, Display, Formatter, Result}; diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 22084dcff8f..7808d42ab5d 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -91,6 +91,7 @@ use crate::{fmt, intrinsics, ops, slice, str}; /// [str]: prim@str "str" #[derive(PartialEq, Eq, Hash)] #[stable(feature = "core_c_str", since = "1.64.0")] +#[rustc_diagnostic_item = "cstr_type"] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 467fa17a6f3..c7c462a4df1 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -78,7 +78,7 @@ impl fmt::Write for PadAdapter<'_, '_> { /// /// assert_eq!( /// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }), -/// "Foo { bar: 10, baz: \"Hello World\" }", +/// r#"Foo { bar: 10, baz: "Hello World" }"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -125,7 +125,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }), - /// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }", + /// r#"Bar { bar: 10, another: "Hello World", nonexistent_field: 1 }"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -237,7 +237,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }), - /// "Bar { bar: 10, baz: \"Hello World\" }", + /// r#"Bar { bar: 10, baz: "Hello World" }"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -280,7 +280,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), -/// "Foo(10, \"Hello World\")", +/// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -322,7 +322,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), - /// "Foo(10, \"Hello World\")", + /// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -360,6 +360,51 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { self } + /// Marks the tuple struct as non-exhaustive, indicating to the reader that there are some + /// other fields that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .finish_non_exhaustive() // Show that some other field(s) exist. + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(10, "secret!".to_owned())), + /// "Foo(10, ..)", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + if self.fields > 0 { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str(")") + } else { + self.fmt.write_str(", ..)") + } + } else { + self.fmt.write_str("(..)") + } + }); + self.result + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -381,7 +426,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(10, "Hello World".to_string())), - /// "Foo(10, \"Hello World\")", + /// r#"Foo(10, "Hello World")"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -555,6 +600,56 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { self } + /// Marks the set as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec<i32>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_set(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "{1, 2, ..}", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result = self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("}") + } else { + self.inner.fmt.write_str(", ..}") + } + } else { + self.inner.fmt.write_str("..}") + } + }); + self.inner.result + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -699,6 +794,55 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { self } + /// Marks the list as non-exhaustive, indicating to the reader that there are some other + /// elements that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec<i32>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_list(); + /// let mut f = f.entries(self.0.iter().take(2)); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![1, 2, 3, 4])), + /// "[1, 2, ..]", + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.inner.result.and_then(|_| { + if self.inner.has_fields { + if self.inner.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.inner.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.inner.fmt.write_str("]") + } else { + self.inner.fmt.write_str(", ..]") + } + } else { + self.inner.fmt.write_str("..]") + } + }) + } + /// Finishes output and returns any error encountered. /// /// # Examples @@ -750,7 +894,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), -/// "{\"A\": 10, \"B\": 11}", +/// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[must_use = "must eventually call `finish()` on Debug builders"] @@ -790,7 +934,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -826,7 +970,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] @@ -902,7 +1046,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}", + /// r#"{"whole": [("A", 10), ("B", 11)]}"#, /// ); /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] @@ -960,7 +1104,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"A\": 10, \"B\": 11}", + /// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] @@ -976,6 +1120,62 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self } + /// Marks the map as non-exhaustive, indicating to the reader that there are some other + /// entries that are not shown in the debug representation. + /// + /// # Examples + /// + /// ``` + /// #![feature(debug_more_non_exhaustive)] + /// + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// // Print at most two elements, abbreviate the rest + /// let mut f = fmt.debug_map(); + /// let mut f = f.entries(self.0.iter().take(2).map(|&(ref k, ref v)| (k, v))); + /// if self.0.len() > 2 { + /// f.finish_non_exhaustive() + /// } else { + /// f.finish() + /// } + /// } + /// } + /// + /// assert_eq!( + /// format!("{:?}", Foo(vec![ + /// ("A".to_string(), 10), + /// ("B".to_string(), 11), + /// ("C".to_string(), 12), + /// ])), + /// r#"{"A": 10, "B": 11, ..}"#, + /// ); + /// ``` + #[unstable(feature = "debug_more_non_exhaustive", issue = "127942")] + pub fn finish_non_exhaustive(&mut self) -> fmt::Result { + self.result = self.result.and_then(|_| { + assert!(!self.has_key, "attempted to finish a map with a partial entry"); + + if self.has_fields { + if self.is_pretty() { + let mut slot = None; + let mut state = Default::default(); + let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); + writer.write_str("..\n")?; + self.fmt.write_str("}") + } else { + self.fmt.write_str(", ..}") + } + } else { + self.fmt.write_str("..}") + } + }); + self.result + } + /// Finishes output and returns any error encountered. /// /// # Panics @@ -1000,7 +1200,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// assert_eq!( /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])), - /// "{\"A\": 10, \"B\": 11}", + /// r#"{"A": 10, "B": 11}"#, /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index bd99e90376a..8cb9accd59d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2949,7 +2949,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { /// sysroot which is built without ub_checks but with `#[rustc_preserve_ub_checks]`. /// For code that gets monomorphized in the user crate (i.e., generic functions and functions with /// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that -/// assertions are enabled whenever the *user crate* has UB checks enabled. However if the +/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] @@ -2957,7 +2957,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { - cfg!(debug_assertions) + cfg!(ub_checks) } /// Allocates a block of memory at compile time. diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 221724d7b4a..59828198099 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -232,7 +232,7 @@ extern "rust-intrinsic" { /// /// `T` must be a vector. /// - /// `U` must be a **const** array of `i32`s. This means it must either refer to a named + /// `U` must be a **const** array or vector of `u32`s. This means it must either refer to a named /// const or be given as an inline const expression (`const { ... }`). /// /// `V` must be a vector with the same element type as `T` and the same length as `U`. diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index c97cd042ab4..5b7d95c2f65 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -104,7 +104,7 @@ macro_rules! float_sum_product { impl Sum for $a { fn sum<I: Iterator<Item=Self>>(iter: I) -> Self { iter.fold( - 0.0, + -0.0, #[rustc_inherit_overflow_checks] |a, b| a + b, ) @@ -126,7 +126,7 @@ macro_rules! float_sum_product { impl<'a> Sum<&'a $a> for $a { fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self { iter.fold( - 0.0, + -0.0, #[rustc_inherit_overflow_checks] |a, b| a + b, ) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e3640627c56..06a745b690a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -110,7 +110,6 @@ #![cfg_attr(bootstrap, feature(offset_of_nested))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] #![feature(const_align_offset)] @@ -194,6 +193,7 @@ // Language features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(asm_const))] +#![cfg_attr(bootstrap, feature(const_fn_floating_point_arithmetic))] #![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] @@ -203,7 +203,7 @@ #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] -#![feature(const_fn_floating_point_arithmetic)] +#![feature(cfg_ub_checks)] #![feature(const_for)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 374fa086aec..5654f5aa4b8 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1097,7 +1097,6 @@ pub mod effects { pub trait TyCompat<T: ?Sized> {} impl<T: ?Sized> TyCompat<T> for T {} - impl<T: ?Sized> TyCompat<T> for Maybe {} impl<T: ?Sized> TyCompat<Maybe> for T {} #[lang = "EffectsIntersection"] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 00c837041b6..be5cee2e852 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -47,6 +47,7 @@ use crate::ptr; #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct ManuallyDrop<T: ?Sized> { value: T, } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f920ab1792d..c308def2f57 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -237,6 +237,7 @@ use crate::{fmt, intrinsics, ptr, slice}; #[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub union MaybeUninit<T> { uninit: (), value: ManuallyDrop<T>, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7a9ca4011be..e602b497d17 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -19,7 +19,7 @@ pub use maybe_uninit::MaybeUninit; mod transmutability; #[unstable(feature = "transmutability", issue = "99571")] -pub use transmutability::{Assume, BikeshedIntrinsicFrom}; +pub use transmutability::{Assume, TransmuteFrom}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(inline)] diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index ea73c5b80ba..049b32ede9c 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -1,40 +1,295 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; -/// Are values of a type transmutable into values of another type? +/// Marks that `Src` is transmutable into `Self`. /// -/// This trait is implemented on-the-fly by the compiler for types `Src` and `Self` when the bits of -/// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`, -/// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied. +/// # Implementation +/// +/// This trait cannot be implemented explicitly. It is implemented on-the-fly by +/// the compiler for all types `Src` and `Self` such that, given a set of safety +/// obligations on the programmer (see [`Assume`]), the compiler has proved that +/// the bits of a value of type `Src` can be soundly reinterpreted as a `Self`. +/// +/// # Safety +/// +/// If `Dst: TransmuteFrom<Src, ASSUMPTIONS>`, the compiler guarantees that +/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided +/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume) +/// are satisfied. +/// +/// A union-transmute is any bit-reinterpretation conversion in the form of: +/// +/// ```rust +/// pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst { +/// use core::mem::ManuallyDrop; +/// +/// #[repr(C)] +/// union Transmute<Src, Dst> { +/// src: ManuallyDrop<Src>, +/// dst: ManuallyDrop<Dst>, +/// } +/// +/// let transmute = Transmute { +/// src: ManuallyDrop::new(src), +/// }; +/// +/// let dst = transmute.dst; +/// +/// ManuallyDrop::into_inner(dst) +/// } +/// ``` +/// +/// Note that this construction is more permissive than +/// [`mem::transmute_copy`](super::transmute_copy); union-transmutes permit +/// conversions that extend the bits of `Src` with trailing padding to fill +/// trailing uninitialized bytes of `Self`; e.g.: +/// +#[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] +#[cfg_attr(not(bootstrap), doc = "```rust")] +/// #![feature(transmutability)] +/// +/// use core::mem::{Assume, TransmuteFrom}; +/// +/// let src = 42u8; // size = 1 +/// +/// #[repr(C, align(2))] +/// struct Dst(u8); // size = 2 +// +/// let _ = unsafe { +/// <Dst as TransmuteFrom<u8, { Assume::SAFETY }>>::transmute(src) +/// }; +/// ``` +/// +/// # Caveats +/// +/// ## Portability +/// +/// Implementations of this trait do not provide any guarantee of portability +/// across toolchains, targets or compilations. This trait may be implemented +/// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains, +/// targets or compilations, but not others. For example, if the layouts of +/// `Src` or `Self` are non-deterministic, the presence or absence of an +/// implementation of this trait may also be non-deterministic. Even if `Src` +/// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs), +/// Rust does not specify the alignments of its primitive integer types, and +/// layouts that involve these types may vary across toolchains, targets or +/// compilations. +/// +/// ## Stability +/// +/// Implementations of this trait do not provide any guarantee of SemVer +/// stability across the crate versions that define the `Src` and `Self` types. +/// If SemVer stability is crucial to your application, you must consult the +/// documentation of `Src` and `Self`s' defining crates. Note that the presence +/// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability. +/// Furthermore, stability does not imply portability. For example, the size of +/// `usize` is stable, but not portable. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_trait"] #[rustc_deny_explicit_impl(implement_via_object = false)] #[rustc_coinductive] -pub unsafe trait BikeshedIntrinsicFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> +pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, { + /// Transmutes a `Src` value into a `Self`. + /// + /// # Safety + /// + /// The safety obligations of the caller depend on the value of `ASSUME`: + /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee + /// that the addresses of references in the returned `Self` satisfy the + /// alignment requirements of their referent types. + /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee + /// that references in the returned `Self` will not outlive their + /// referents. + /// - If [`ASSUME.safety`](Assume::safety), the returned value might not + /// satisfy the library safety invariants of `Self`, and the caller must + /// guarantee that undefined behavior does not arise from uses of the + /// returned value. + /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee + /// that `src` is a bit-valid instance of `Self`. + /// + /// When satisfying the above obligations (if any), the caller must *not* + /// assume that this trait provides any inherent guarantee of layout + /// [portability](#portability) or [stability](#stability). + unsafe fn transmute(src: Src) -> Self + where + Src: Sized, + Self: Sized, + { + use super::ManuallyDrop; + + #[repr(C)] + union Transmute<Src, Dst> { + src: ManuallyDrop<Src>, + dst: ManuallyDrop<Dst>, + } + + let transmute = Transmute { src: ManuallyDrop::new(src) }; + + // SAFETY: It is safe to reinterpret the bits of `src` as a value of + // type `Self`, because, by combination of invariant on this trait and + // contract on the caller, `src` has been proven to satisfy both the + // language and library invariants of `Self`. For all invariants not + // `ASSUME`'d by the caller, the safety obligation is supplied by the + // compiler. Conversely, for all invariants `ASSUME`'d by the caller, + // the safety obligation is supplied by contract on the caller. + let dst = unsafe { transmute.dst }; + + ManuallyDrop::into_inner(dst) + } } -/// What transmutation safety conditions shall the compiler assume that *you* are checking? +/// Configurable proof assumptions of [`TransmuteFrom`]. +/// +/// When `false`, the respective proof obligation belongs to the compiler. When +/// `true`, the onus of the safety proof belongs to the programmer. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_opts"] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Assume { - /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that - /// destination referents do not have stricter alignment requirements than source referents. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the the alignment requirements of references; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::{align_of, TransmuteFrom}; + /// + /// assert_eq!(align_of::<[u8; 2]>(), 1); + /// assert_eq!(align_of::<u16>(), 2); + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let dst: &u16 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that references in the transmuted value satisfy the alignment + /// requirements of their referent types; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(pointer_is_aligned_to, transmutability)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::<u16>()) { + /// // SAFETY: We have checked above that the address of `src` satisfies the + /// // alignment requirements of `u16`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None)); + /// ``` pub alignment: bool, - /// When `true`, the compiler assume that *you* are ensuring that lifetimes are not extended in a manner - /// that violates Rust's memory model. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that extend the lifetimes of references. + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that + /// references in the transmuted value do not outlive their referents. pub lifetimes: bool, - /// When `true`, the compiler assumes that *you* have ensured that no - /// unsoundness will arise from violating the safety invariants of the - /// destination type (and sometimes of the source type, too). + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the library safety invariants of the destination + /// type; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// // SAFETY: No safety obligations. + /// let dst: EvenU8 = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that undefined behavior does not arise from using the transmuted value; + /// e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 42; + /// + /// struct EvenU8 { + /// // SAFETY: `val` must be an even number. + /// val: u8, + /// } + /// + /// let maybe_dst: Option<EvenU8> = if src % 2 == 0 { + /// // SAFETY: We have checked above that the value of `src` is even. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 }))); + /// ``` pub safety: bool, - /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid - /// instance of the destination type. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the language-level bit-validity invariant of the + /// destination type; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// #![feature(transmutability)] + /// use core::mem::TransmuteFrom; + /// + /// let src: u8 = 3; + /// + /// // SAFETY: No safety obligations. + /// let dst: bool = unsafe { + /// <_ as TransmuteFrom<_>>::transmute(src) + /// }; + /// ``` + /// + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured + /// that the value being transmuted is a bit-valid instance of the + /// transmuted value; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::{Assume, TransmuteFrom}; + /// + /// let src: u8 = 1; + /// + /// let maybe_dst: Option<bool> = if src == 0 || src == 1 { + /// // SAFETY: We have checked above that the value of `src` is a bit-valid + /// // instance of `bool`. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src) + /// }) + /// } else { + /// None + /// }; + /// + /// assert_eq!(maybe_dst, Some(true)); + /// ``` pub validity: bool, } @@ -44,29 +299,86 @@ impl ConstParamTy_ for Assume {} impl UnsizedConstParamTy for Assume {} impl Assume { - /// Do not assume that *you* have ensured any safety properties are met. + /// With this, [`TransmuteFrom`] does not assume you have ensured any safety + /// obligations are met, and relies only upon its own analysis to (dis)prove + /// transmutability. #[unstable(feature = "transmutability", issue = "99571")] pub const NOTHING: Self = Self { alignment: false, lifetimes: false, safety: false, validity: false }; - /// Assume only that alignment conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value satisfy the alignment requirements of + /// their referent types. See [`Assume::alignment`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING }; - /// Assume only that lifetime conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value do not outlive their referents. See + /// [`Assume::lifetimes`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING }; - /// Assume only that safety conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// undefined behavior does not arise from using the transmuted value. See + /// [`Assume::safety`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING }; - /// Assume only that dynamically-satisfiable validity conditions are met. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that the + /// value being transmuted is a bit-valid instance of the transmuted value. + /// See [`Assume::validity`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING }; - /// Assume both `self` and `other_assumptions`. + /// Combine the assumptions of `self` and `other_assumptions`. + /// + /// This is especially useful for extending [`Assume`] in generic contexts; + /// e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] #[unstable(feature = "transmutability", issue = "99571")] + /// #![feature( + /// adt_const_params, + /// generic_const_exprs, + /// pointer_is_aligned_to, + /// transmutability, + /// )] + /// #![allow(incomplete_features)] + /// use core::mem::{align_of, Assume, TransmuteFrom}; + /// + /// /// Attempts to transmute `src` to `&Dst`. + /// /// + /// /// Returns `None` if `src` violates the alignment requirements of `&Dst`. + /// /// + /// /// # Safety + /// /// + /// /// The caller guarantees that the obligations required by `ASSUME`, except + /// /// alignment, are satisfied. + /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst> + /// where + /// &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>, + /// { + /// if <*const _>::is_aligned_to(src, align_of::<Dst>()) { + /// // SAFETY: By the above dynamic check, we have ensured that the address + /// // of `src` satisfies the alignment requirements of `&Dst`. By contract + /// // on the caller, the safety obligations required by `ASSUME` have also + /// // been satisfied. + /// Some(unsafe { + /// <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src) + /// }) + /// } else { + /// None + /// } + /// } + /// + /// let src: &[u8; 2] = &[0xFF, 0xFF]; + /// + /// // SAFETY: No safety obligations. + /// let maybe_dst: Option<&u16> = unsafe { + /// try_transmute_ref::<_, _, { Assume::NOTHING }>(src) + /// }; + ///``` pub const fn and(self, other_assumptions: Self) -> Self { Self { alignment: self.alignment || other_assumptions.alignment, @@ -76,7 +388,21 @@ impl Assume { } } - /// Assume `self`, excepting `other_assumptions`. + /// Remove `other_assumptions` the obligations of `self`; e.g.: + /// + #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] + #[cfg_attr(not(bootstrap), doc = "```rust")] + /// #![feature(transmutability)] + /// use core::mem::Assume; + /// + /// let assumptions = Assume::ALIGNMENT.and(Assume::SAFETY); + /// let to_be_removed = Assume::SAFETY.and(Assume::VALIDITY); + /// + /// assert_eq!( + /// assumptions.but_not(to_be_removed), + /// Assume::ALIGNMENT, + /// ); + /// ``` #[unstable(feature = "transmutability", issue = "99571")] pub const fn but_not(self, other_assumptions: Self) -> Self { Self { diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 38e69e7641a..d4236e47bfe 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -454,11 +454,14 @@ impl f128 { } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f128) for more info. + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -477,11 +480,14 @@ impl f128 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f128) for more info. + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -750,7 +756,7 @@ impl f128 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f128) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -791,7 +797,7 @@ impl f128 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f128) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f128", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 41bd34a2702..1e2f841aca7 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -261,7 +261,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let nan = f16::NAN; /// let f = 7.0_f16; @@ -293,7 +293,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let f = 7.0f16; /// let inf = f16::INFINITY; @@ -319,7 +319,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let f = 7.0f16; /// let inf: f16 = f16::INFINITY; @@ -347,7 +347,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -377,7 +377,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -409,7 +409,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// use std::num::FpCategory; /// @@ -464,11 +464,14 @@ impl f16 { } /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with - /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f16) for more info. + /// positive sign bit and positive infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_positive` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -490,11 +493,14 @@ impl f16 { } /// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with - /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any - /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that - /// the bit pattern of NaNs are conserved over arithmetic operations, the result of - /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f16) for more info. + /// negative sign bit and negative infinity. + /// + /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of + /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are + /// conserved over arithmetic operations, the result of `is_sign_negative` on + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -762,7 +768,7 @@ impl f16 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f16) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -802,7 +808,7 @@ impl f16 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f16) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[inline] #[unstable(feature = "f16", issue = "116909")] // #[unstable(feature = "float_minimum_maximum", issue = "91079")] @@ -867,7 +873,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = 4.6_f16; /// let rounded = unsafe { value.to_int_unchecked::<u16>() }; @@ -910,7 +916,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// # // FIXME(f16_f128): enable this once const casting works /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! @@ -958,7 +964,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let v = f16::from_bits(0x4a40); /// assert_eq!(v, 12.5); @@ -1071,7 +1077,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_be_bytes([0x4a, 0x40]); /// assert_eq!(value, 12.5); @@ -1094,7 +1100,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_le_bytes([0x40, 0x4a]); /// assert_eq!(value, 12.5); @@ -1124,7 +1130,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x4a, 0x40] @@ -1257,7 +1263,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0); /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0); diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 719727e2f1e..c1adcc753f2 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -700,8 +700,9 @@ impl f32 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_positive` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f32; @@ -724,8 +725,9 @@ impl f32 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_negative` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0f32; @@ -954,7 +956,7 @@ impl f32 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -989,7 +991,7 @@ impl f32 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 85eb152ad1f..e6406771ad3 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -695,8 +695,9 @@ impl f64 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_positive` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -728,8 +729,9 @@ impl f64 { /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are /// conserved over arithmetic operations, the result of `is_sign_negative` on - /// a NaN might produce an unexpected result in some cases. See [explanation - /// of NaN as a special value](f32) for more info. + /// a NaN might produce an unexpected or non-portable result. See the [specification + /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -968,7 +970,7 @@ impl f64 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] @@ -1003,7 +1005,7 @@ impl f64 { /// Note that this follows the semantics specified in IEEE 754-2019. /// /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN - /// operand is conserved; see [explanation of NaN as a special value](f32) for more info. + /// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info. #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 17cf2a7b261..42461a3345b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1312,6 +1312,34 @@ macro_rules! int_impl { } } + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is /// larger than or equal to the number of bits in `self`. /// @@ -1410,6 +1438,40 @@ macro_rules! int_impl { } } + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, which yields `0` for a positive number, + /// and `-1` for a negative number. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + // A shift by `Self::BITS-1` suffices for signed integers, because the sign bit is copied for each of the shifted bits. + + // SAFETY: + // `Self::BITS-1` is guaranteed to be less than `Self::BITS` + unsafe { self.unchecked_shr(Self::BITS - 1) } + } + } + /// Checked absolute value. Computes `self.abs()`, returning `None` if /// `self == MIN`. /// @@ -2826,8 +2888,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2865,8 +2927,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and + /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2881,6 +2943,11 @@ macro_rules! int_impl { /// assert_eq!(a.rem_euclid(-b), 3); /// assert_eq!((-a).rem_euclid(-b), 1); /// ``` + /// + /// This will panic: + /// ```should_panic + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.rem_euclid(-1);")] + /// ``` #[doc(alias = "modulo", alias = "mod")] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] @@ -2909,8 +2976,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2945,8 +3012,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 719a6a55940..0d0bbc5256f 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1501,6 +1501,34 @@ macro_rules! uint_impl { } } + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] + #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shl(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shl(rhs) } + } else { + 0 + } + } + /// Checked shift right. Computes `self >> rhs`, returning `None` /// if `rhs` is larger than or equal to the number of bits in `self`. /// @@ -1599,6 +1627,34 @@ macro_rules! uint_impl { } } + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// + /// If `rhs` is larger or equal to the number of bits in `self`, + /// the entire value is shifted out, and `0` is returned. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(unbounded_shifts)] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] + #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] + /// ``` + #[unstable(feature = "unbounded_shifts", issue = "129375")] + #[rustc_const_unstable(feature = "const_unbounded_shifts", issue = "129375")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unbounded_shr(self, rhs: u32) -> $SelfT{ + if rhs < Self::BITS { + // SAFETY: + // rhs is just checked to be in-range above + unsafe { self.unchecked_shr(rhs) } + } else { + 0 + } + } + /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// overflow occurred. /// diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 930edffd505..e2a842046a9 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -195,6 +195,7 @@ impl<'a> Location<'a> { #[stable(feature = "panic_hook_display", since = "1.26.0")] impl fmt::Display for Location<'_> { + #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { write!(formatter, "{}:{}:{}", self.file, self.line, self.col) } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 0569b8b7624..65f6bfb7ee1 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1084,6 +1084,7 @@ use crate::{cmp, fmt}; #[lang = "pin"] #[fundamental] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] #[derive(Copy, Clone)] pub struct Pin<Ptr> { // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: @@ -1291,8 +1292,8 @@ impl<Ptr: Deref> Pin<Ptr> { /// // Now, if `x` was the only reference, we have a mutable reference to /// // data that we pinned above, which we could use to move it as we have /// // seen in the previous example. We have violated the pinning API contract. - /// } - /// ``` + /// } + /// ``` /// /// ## Pinning of closure captures /// @@ -1369,33 +1370,14 @@ impl<Ptr: Deref> Pin<Ptr> { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&*self.__pointer) } } - - /// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`. - /// - /// # Safety - /// - /// This function is unsafe. You must guarantee that you will continue to - /// treat the pointer `Ptr` as pinned after you call this function, so that - /// the invariants on the `Pin` type can be upheld. If the code using the - /// resulting `Ptr` does not continue to maintain the pinning invariants that - /// is a violation of the API contract and may lead to undefined behavior in - /// later (safe) operations. - /// - /// Note that you must be able to guarantee that the data pointed to by `Ptr` - /// will be treated as pinned all the way until its `drop` handler is complete! - /// - /// *For more information, see the [`pin` module docs][self]* - /// - /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used - /// instead. - #[inline(always)] - #[rustc_const_unstable(feature = "const_pin", issue = "76654")] - #[stable(feature = "pin_into_inner", since = "1.39.0")] - pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr { - pin.__pointer - } } +// These methods being in a `Ptr: DerefMut` impl block concerns semver stability. +// Currently, calling e.g. `.set()` on a `Pin<&T>` sees that `Ptr: DerefMut` +// doesn't hold, and goes to check for a `.set()` method on `T`. But, if the +// `where Ptr: DerefMut` bound is moved to the method, rustc sees the impl block +// as a valid candidate, and doesn't go on to check other candidates when it +// sees that the bound on the method. impl<Ptr: DerefMut> Pin<Ptr> { /// Gets a mutable reference to the pinned value this `Pin<Ptr>` points to. /// @@ -1433,6 +1415,44 @@ impl<Ptr: DerefMut> Pin<Ptr> { unsafe { Pin::new_unchecked(&mut *self.__pointer) } } + /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. + /// + /// This is a generic method to go from `Pin<&mut Pin<Pointer<T>>>` to `Pin<&mut T>`. It is + /// safe because the existence of a `Pin<Pointer<T>>` ensures that the pointee, `T`, cannot + /// move in the future, and this method does not enable the pointee to move. "Malicious" + /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of + /// `Pin::new_unchecked`. + #[unstable(feature = "pin_deref_mut", issue = "86918")] + #[must_use = "`self` will be dropped if the result is not used"] + #[inline(always)] + pub fn as_deref_mut(self: Pin<&mut Pin<Ptr>>) -> Pin<&mut Ptr::Target> { + // SAFETY: What we're asserting here is that going from + // + // Pin<&mut Pin<Ptr>> + // + // to + // + // Pin<&mut Ptr::Target> + // + // is safe. + // + // We need to ensure that two things hold for that to be the case: + // + // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. + // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating + // `Pin<&mut Pin<Ptr>>` + // + // The existence of `Pin<Ptr>` is sufficient to guarantee #1: since we already have a + // `Pin<Ptr>`, it must already uphold the pinning guarantees, which must mean that + // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely + // on the fact that `Ptr` is _also_ pinned. + // + // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the + // `Pin<Ptr>` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains + // any access to the `Ptr` itself, much less the `Pin<Ptr>`. + unsafe { self.get_unchecked_mut() }.as_mut() + } + /// Assigns a new value to the memory location pointed to by the `Pin<Ptr>`. /// /// This overwrites pinned data, but that is okay: the original pinned value's destructor gets @@ -1463,6 +1483,33 @@ impl<Ptr: DerefMut> Pin<Ptr> { } } +impl<Ptr: Deref> Pin<Ptr> { + /// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will continue to + /// treat the pointer `Ptr` as pinned after you call this function, so that + /// the invariants on the `Pin` type can be upheld. If the code using the + /// resulting `Ptr` does not continue to maintain the pinning invariants that + /// is a violation of the API contract and may lead to undefined behavior in + /// later (safe) operations. + /// + /// Note that you must be able to guarantee that the data pointed to by `Ptr` + /// will be treated as pinned all the way until its `drop` handler is complete! + /// + /// *For more information, see the [`pin` module docs][self]* + /// + /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used + /// instead. + #[inline(always)] + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + #[stable(feature = "pin_into_inner", since = "1.39.0")] + pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr { + pin.__pointer + } +} + impl<'a, T: ?Sized> Pin<&'a T> { /// Constructs a new pin by mapping the interior value. /// @@ -1613,46 +1660,6 @@ impl<T: ?Sized> Pin<&'static T> { } } -impl<'a, Ptr: DerefMut> Pin<&'a mut Pin<Ptr>> { - /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. - /// - /// This is a generic method to go from `Pin<&mut Pin<Pointer<T>>>` to `Pin<&mut T>`. It is - /// safe because the existence of a `Pin<Pointer<T>>` ensures that the pointee, `T`, cannot - /// move in the future, and this method does not enable the pointee to move. "Malicious" - /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of - /// `Pin::new_unchecked`. - #[unstable(feature = "pin_deref_mut", issue = "86918")] - #[must_use = "`self` will be dropped if the result is not used"] - #[inline(always)] - pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> { - // SAFETY: What we're asserting here is that going from - // - // Pin<&mut Pin<Ptr>> - // - // to - // - // Pin<&mut Ptr::Target> - // - // is safe. - // - // We need to ensure that two things hold for that to be the case: - // - // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out. - // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating - // `Pin<&mut Pin<Ptr>>` - // - // The existence of `Pin<Ptr>` is sufficient to guarantee #1: since we already have a - // `Pin<Ptr>`, it must already uphold the pinning guarantees, which must mean that - // `Pin<&mut Ptr::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely - // on the fact that `Ptr` is _also_ pinned. - // - // For #2, we need to ensure that code given a `Pin<&mut Ptr::Target>` cannot cause the - // `Pin<Ptr>` to move? That is not possible, since `Pin<&mut Ptr::Target>` no longer retains - // any access to the `Ptr` itself, much less the `Pin<Ptr>`. - unsafe { self.get_unchecked_mut() }.as_mut() - } -} - impl<T: ?Sized> Pin<&'static mut T> { /// Gets a pinning mutable reference from a static mutable reference. /// diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 09ebef89fb0..fe6ed7e0cf3 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1130,8 +1130,8 @@ impl<T> (T,) {} /// A 16-bit floating point type (specifically, the "binary16" type defined in IEEE 754-2008). /// /// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many -/// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on -/// half-precision values][wikipedia] for more information. +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on half-precision +/// values][wikipedia] for more information. /// /// Note that most common platforms will not support `f16` in hardware without enabling extra target /// features, with the notable exception of Apple Silicon (also known as M1, M2, etc.) processors. @@ -1190,6 +1190,11 @@ mod prim_f16 {} /// portable or even fully deterministic! This means that there may be some /// surprising results upon inspecting the bit patterns, /// as the same calculations might produce NaNs with different bit patterns. +/// This also affects the sign of the NaN: checking `is_sign_positive` or `is_sign_negative` on +/// a NaN is the most common way to run into these surprising results. +/// (Checking `x >= 0.0` or `x <= 0.0` avoids those surprises, but also how negative/positive +/// zero are treated.) +/// See the section below for what exactly is guaranteed about the bit pattern of a NaN. /// /// When a primitive operation (addition, subtraction, multiplication, or /// division) is performed on this type, the result is rounded according to the @@ -1211,6 +1216,79 @@ mod prim_f16 {} /// *[See also the `std::f32::consts` module](crate::f32::consts).* /// /// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format +/// +/// # NaN bit patterns +/// +/// This section defines the possible NaN bit patterns returned by non-"bitwise" floating point +/// operations. The bitwise operations are unary `-`, `abs`, `copysign`; those are guaranteed to +/// exactly preserve the bit pattern of their input except for possibly changing the sign bit. +/// +/// A floating-point NaN value consists of: +/// - a sign bit +/// - a quiet/signaling bit +/// - a payload, which makes up the rest of the significand (i.e., the mantissa) except for the +/// quiet/signaling bit. +/// +/// Rust assumes that the quiet/signaling bit being set to `1` indicates a quiet NaN (QNaN), and a +/// value of `0` indicates a signaling NaN (SNaN). In the following we will hence just call it the +/// "quiet bit". +/// +/// The following rules apply when a NaN value is returned: the result has a non-deterministic sign. +/// The quiet bit and payload are non-deterministically chosen from the following set of options: +/// +/// - **Preferred NaN**: The quiet bit is set and the payload is all-zero. +/// - **Quieting NaN propagation**: The quiet bit is set and the payload is copied from any input +/// operand that is a NaN. If the inputs and outputs do not have the same payload size (i.e., for +/// `as` casts), then +/// - If the output is smaller than the input, low-order bits of the payload get dropped. +/// - If the output is larger than the input, the payload gets filled up with 0s in the low-order +/// bits. +/// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand +/// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the +/// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller +/// than the input, droppig the low-order bits may result in a payload of 0; a payload of 0 is not +/// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN +/// propagation cannot occur with some inputs. +/// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific +/// set of "extra" possible NaN payloads. The set can depend on the input operand values. +/// See the table below for the concrete NaNs this set contains on various targets. +/// +/// In particular, if all input NaNs are quiet (or if there are no input NaNs), then the output NaN +/// is definitely quiet. Signaling NaN outputs can only occur if they are provided as an input +/// value. Similarly, if all input NaNs are preferred (or if there are no input NaNs) and the target +/// does not have any "extra" NaN payloads, then the output NaN is guaranteed to be preferred. +/// +/// The non-deterministic choice happens when the operation is executed; i.e., the result of a +/// NaN-producing floating point operation is a stable bit pattern (looking at these bits multiple +/// times will yield consistent results), but running the same operation twice with the same inputs +/// can produce different results. +/// +/// These guarantees are neither stronger nor weaker than those of IEEE 754: IEEE 754 guarantees +/// that an operation never returns a signaling NaN, whereas it is possible for operations like +/// `SNAN * 1.0` to return a signaling NaN in Rust. Conversely, IEEE 754 makes no statement at all +/// about which quiet NaN is returned, whereas Rust restricts the set of possible results to the +/// ones listed above. +/// +/// Unless noted otherwise, the same rules also apply to NaNs returned by other library functions +/// (e.g. `min`, `minimum`, `max`, `maximum`); other aspects of their semantics and which IEEE 754 +/// operation they correspond to are documented with the respective functions. +/// +/// When a floating-point operation is executed in `const` context, the same rules apply: no +/// guarantee is made about which of the NaN bit patterns described above will be returned. The +/// result does not have to match what happens when executing the same code at runtime, and the +/// result can vary depending on factors such as compiler version and flags. +/// +/// ### Target-specific "extra" NaN values +// FIXME: Is there a better place to put this? +/// +/// | `target_arch` | Extra payloads possible on this platform | +/// |---------------|---------| +/// | `x86`, `x86_64`, `arm`, `aarch64`, `riscv32`, `riscv64` | None | +/// | `sparc`, `sparc64` | The all-one payload | +/// | `wasm32`, `wasm64` | If all input NaNs are quiet with all-zero payload: None.<br> Otherwise: all possible payloads. | +/// +/// For targets not in this table, all payloads are possible. + #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} @@ -1218,14 +1296,12 @@ mod prim_f32 {} #[doc(alias = "double")] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// -/// This type is very similar to [`f32`], but has increased -/// precision by using twice as many bits. Please see [the documentation for -/// `f32`][`f32`] or [Wikipedia on double precision +/// This type is very similar to [`prim@f32`], but has increased precision by using twice as many +/// bits. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on double-precision /// values][wikipedia] for more information. /// /// *[See also the `std::f64::consts` module](crate::f64::consts).* /// -/// [`f32`]: prim@f32 /// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} @@ -1235,12 +1311,12 @@ mod prim_f64 {} /// A 128-bit floating point type (specifically, the "binary128" type defined in IEEE 754-2008). /// /// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice -/// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on +/// as many bits as `f64`. Please see [the documentation for `f32`](prim@f32) or [Wikipedia on /// quad-precision values][wikipedia] for more information. /// /// Note that no platforms have hardware support for `f128` without enabling target specific features, /// as for all instruction set architectures `f128` is considered an optional feature. -/// Only Power ISA ("PowerPC") and RISCV specify it, and only certain microarchitectures +/// Only Power ISA ("PowerPC") and RISC-V specify it, and only certain microarchitectures /// actually implement it. For x86-64 and AArch64, ISA support is not even specified, /// so it will always be a software implementation significantly slower than `f64`. /// diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 68fce3960c7..19fe03d57cc 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,5 +1,4 @@ use crate::num::NonZero; -#[cfg(debug_assertions)] use crate::ub_checks::assert_unsafe_precondition; use crate::{cmp, fmt, hash, mem, num}; @@ -77,7 +76,6 @@ impl Alignment { #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { - #[cfg(debug_assertions)] assert_unsafe_precondition!( check_language_ub, "Alignment::new_unchecked requires a power of two", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 93bbd92593f..3b635e2a4aa 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -239,24 +239,7 @@ impl<T: ?Sized> *const T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -302,24 +285,8 @@ impl<T: ?Sized> *const T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -350,20 +317,7 @@ impl<T: ?Sized> *const T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 3fe5212cea7..d7ed4edcc00 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -56,6 +56,44 @@ //! has size 0, i.e., even if memory is not actually touched. Consider using //! [`NonNull::dangling`] in such cases. //! +//! ## Pointer to reference conversion +//! +//! When converting a pointer to a reference (e.g. via `&*ptr` or `&mut *ptr`), +//! there are several rules that must be followed: +//! +//! * The pointer must be properly aligned. +//! +//! * It must be non-null. +//! +//! * It must be "dereferenceable" in the sense defined above. +//! +//! * The pointer must point to a [valid value] of type `T`. +//! +//! * You must enforce Rust's aliasing rules. The exact aliasing rules are not decided yet, so we +//! only give a rough overview here. The rules also depend on whether a mutable or a shared +//! reference is being created. +//! * When creating a mutable reference, then while this reference exists, the memory it points to +//! must not get accessed (read or written) through any other pointer or reference not derived +//! from this reference. +//! * When creating a shared reference, then while this reference exists, the memory it points to +//! must not get mutated (except inside `UnsafeCell`). +//! +//! If a pointer follows all of these rules, it is said to be +//! *convertible to a (mutable or shared) reference*. +// ^ we use this term instead of saying that the produced reference must +// be valid, as the validity of a reference is easily confused for the +// validity of the thing it refers to, and while the two concepts are +// closly related, they are not identical. +//! +//! These rules apply even if the result is unused! +//! (The part about being initialized is not yet fully decided, but until +//! it is, the only safe approach is to ensure that they are indeed initialized.) +//! +//! An example of the implications of the above rules is that an expression such +//! as `unsafe { &*(0 as *const u8) }` is Immediate Undefined Behavior. +//! +//! [valid value]: ../../reference/behavior-considered-undefined.html#invalid-values +//! //! ## Allocated object //! //! An *allocated object* is a subset of program memory which is addressable @@ -2130,6 +2168,33 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool { (p as *const ()) == (q as *const ()) } +/// Compares the *addresses* of the two function pointers for equality. +/// +/// Function pointers comparisons can have surprising results since +/// they are never guaranteed to be unique and could vary between different +/// code generation units. Furthermore, different functions could have the +/// same address after being merged together. +/// +/// This is the same as `f == g` but using this function makes clear +/// that you are aware of these potentially surprising semantics. +/// +/// # Examples +/// +/// ``` +/// #![feature(ptr_fn_addr_eq)] +/// use std::ptr; +/// +/// fn a() { println!("a"); } +/// fn b() { println!("b"); } +/// assert!(!ptr::fn_addr_eq(a as fn(), b as fn())); +/// ``` +#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")] +#[inline(always)] +#[must_use = "function pointer comparison produces a value"] +pub fn fn_addr_eq<T: FnPtr, U: FnPtr>(f: T, g: U) -> bool { + f.addr() == g.addr() +} + /// Hash a raw pointer. /// /// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly) diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index bcf9b889182..42975cc927b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -247,24 +247,7 @@ impl<T: ?Sized> *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -313,24 +296,7 @@ impl<T: ?Sized> *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -364,20 +330,9 @@ impl<T: ?Sized> *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit<T>`, the + /// source pointer can point to uninitialized memory. /// /// # Examples /// @@ -609,25 +564,10 @@ impl<T: ?Sized> *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. + /// When calling this method, you have to ensure that *either* + /// the pointer is null *or* + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety /// /// # Examples /// @@ -675,24 +615,8 @@ impl<T: ?Sized> *mut T { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -727,20 +651,7 @@ impl<T: ?Sized> *mut T { /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is null *or* - /// all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d6be37a76bb..b1429fff744 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -126,20 +126,10 @@ impl<T: Sized> NonNull<T> { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit<T>`, the + /// source pointer can point to uninitialized memory. #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] @@ -160,20 +150,10 @@ impl<T: Sized> NonNull<T> { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// - /// [the module documentation]: crate::ptr#safety + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). + /// Note that because the created reference is to `MaybeUninit<T>`, the + /// source pointer can point to uninitialized memory. #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] @@ -359,22 +339,8 @@ impl<T: ?Sized> NonNull<T> { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get mutated (except inside `UnsafeCell`). - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// /// # Examples /// @@ -410,22 +376,8 @@ impl<T: ?Sized> NonNull<T> { /// /// # Safety /// - /// When calling this method, you have to ensure that all of the following is true: - /// - /// * The pointer must be properly aligned. - /// - /// * It must be "dereferenceable" in the sense defined in [the module documentation]. - /// - /// * The pointer must point to an initialized instance of `T`. - /// - /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is - /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. - /// In particular, while this reference exists, the memory the pointer points to must - /// not get accessed (read or written) through any other pointer. - /// - /// This applies even if the result of this method is unused! - /// (The part about being initialized is not yet fully decided, but until - /// it is, the only safe approach is to ensure that they are indeed initialized.) + /// When calling this method, you have to ensure that + /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). /// # Examples /// /// ``` diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c76157720b7..c7918499d4a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3667,8 +3667,8 @@ impl<T> [T] { { // The panic code path was put into a cold function to not bloat the // call site. - #[inline(never)] - #[cold] + #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] + #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { panic!( diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index db0c5c72822..fae628a7c14 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -840,7 +840,8 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>( } } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] fn panic_on_ord_violation() -> ! { // This is indicative of a logic bug in the user-provided comparison function or Ord // implementation. They are expected to implement a total order as explained in the Ord diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 06f796f9f3a..681ec79c0b7 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -241,24 +241,35 @@ impl<'a> CharIndices<'a> { /// Returns the byte position of the next character, or the length /// of the underlying string if there are no more characters. /// + /// This means that, when the iterator has not been fully consumed, + /// the returned value will match the index that will be returned + /// by the next call to [`next()`](Self::next). + /// /// # Examples /// /// ``` - /// #![feature(char_indices_offset)] /// let mut chars = "a楽".char_indices(); /// + /// // `next()` has not been called yet, so `offset()` returns the byte + /// // index of the first character of the string, which is always 0. /// assert_eq!(chars.offset(), 0); + /// // As expected, the first call to `next()` also returns 0 as index. /// assert_eq!(chars.next(), Some((0, 'a'))); /// + /// // `next()` has been called once, so `offset()` returns the byte index + /// // of the second character ... /// assert_eq!(chars.offset(), 1); + /// // ... which matches the index returned by the next call to `next()`. /// assert_eq!(chars.next(), Some((1, '楽'))); /// + /// // Once the iterator has been consumed, `offset()` returns the length + /// // in bytes of the string. /// assert_eq!(chars.offset(), 4); /// assert_eq!(chars.next(), None); /// ``` #[inline] #[must_use] - #[unstable(feature = "char_indices_offset", issue = "83871")] + #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")] pub fn offset(&self) -> usize { self.front_offset } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index bfa1cf096e2..6aab22177ab 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -5,6 +5,8 @@ use crate::ops::{self, ControlFlow}; /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. +/// +/// This is returned by [`Future::poll`](core::future::Future::poll). #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[lang = "Poll"] diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 65d4d5cf2ce..9ec92e28450 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -122,23 +122,29 @@ macro_rules! tuple_impls { } } - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { - #[inline] - #[allow(non_snake_case)] - fn from(array: [T; ${count($T)}]) -> Self { - let [$($T,)+] = array; - ($($T,)+) + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) { + #[inline] + #[allow(non_snake_case)] + fn from(array: [T; ${count($T)}]) -> Self { + let [$($T,)+] = array; + ($($T,)+) + } } } - #[stable(feature = "array_tuple_conv", since = "1.71.0")] - impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { - #[inline] - #[allow(non_snake_case)] - fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { - let ($($T,)+) = tuple; - [$($T,)+] + maybe_tuple_doc! { + $($T)+ @ + #[stable(feature = "array_tuple_conv", since = "1.71.0")] + impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] { + #[inline] + #[allow(non_snake_case)] + fn from(tuple: ($(${ignore($T)} T,)+)) -> Self { + let ($($T,)+) = tuple; + [$($T,)+] + } } } } @@ -148,7 +154,7 @@ macro_rules! tuple_impls { // Otherwise, it hides the docs entirely. macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[doc(fake_variadic)] + #[cfg_attr(not(bootstrap), doc(fake_variadic))] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index b65b48c162d..c1a8c34539e 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -10,7 +10,7 @@ use crate::intrinsics::{self, const_eval_select}; /// macro for language UB are always ignored. /// /// This macro should be called as -/// `assert_unsafe_precondition!(check_{library,lang}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)` +/// `assert_unsafe_precondition!(check_{library,language}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)` /// where each `expr` will be evaluated and passed in as function argument `ident: type`. Then all /// those arguments are passed to a function with the body `check_expr`. /// Pick `check_language_ub` when this is guarding a violation of language UB, i.e., immediate UB diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs index 2bdc334b7c0..ba4801f5912 100644 --- a/library/core/tests/fmt/builders.rs +++ b/library/core/tests/fmt/builders.rs @@ -79,23 +79,23 @@ mod debug_struct { } assert_eq!( - "Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }", + r#"Bar { foo: Foo { bar: true, baz: 10/20 }, hello: "world" }"#, format!("{Bar:?}") ); assert_eq!( - "Bar { + r#"Bar { foo: Foo { bar: true, baz: 10/20, }, - hello: \"world\", -}", + hello: "world", +}"#, format!("{Bar:#?}") ); } #[test] - fn test_only_non_exhaustive() { + fn test_empty_non_exhaustive() { struct Foo; impl fmt::Debug for Foo { @@ -157,19 +157,19 @@ mod debug_struct { } assert_eq!( - "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }", + r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: "world", .. }"#, format!("{Bar:?}") ); assert_eq!( - "Bar { + r#"Bar { foo: Foo { bar: true, baz: 10/20, .. }, - hello: \"world\", + hello: "world", .. -}", +}"#, format!("{Bar:#?}") ); } @@ -249,15 +249,89 @@ mod debug_tuple { } } - assert_eq!("Bar(Foo(true, 10/20), \"world\")", format!("{Bar:?}")); + assert_eq!(r#"Bar(Foo(true, 10/20), "world")"#, format!("{Bar:?}")); assert_eq!( - "Bar( + r#"Bar( Foo( true, 10/20, ), - \"world\", + "world", +)"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo").finish_non_exhaustive() + } + } + + assert_eq!("Foo(..)", format!("{Foo:?}")); + assert_eq!("Foo(..)", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("Foo(true, 10/20, ..)", format!("{Foo:?}")); + assert_eq!( + "Foo( + true, + 10/20, + .. )", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Bar").field(&Foo).field(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"Bar(Foo(true, 10/20, ..), "world", ..)"#, format!("{Bar:?}")); + assert_eq!( + r#"Bar( + Foo( + true, + 10/20, + .. + ), + "world", + .. +)"#, format!("{Bar:#?}") ); } @@ -301,11 +375,11 @@ mod debug_map { assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); - assert_eq!("{\"bar\": true}", format!("{Entry:?}")); + assert_eq!(r#"{"bar": true}"#, format!("{Entry:?}")); assert_eq!( - "{ - \"bar\": true, -}", + r#"{ + "bar": true, +}"#, format!("{Entry:#?}") ); } @@ -339,12 +413,12 @@ mod debug_map { assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); - assert_eq!("{\"bar\": true, 10: 10/20}", format!("{Entry:?}")); + assert_eq!(r#"{"bar": true, 10: 10/20}"#, format!("{Entry:?}")); assert_eq!( - "{ - \"bar\": true, + r#"{ + "bar": true, 10: 10/20, -}", +}"#, format!("{Entry:#?}") ); } @@ -371,21 +445,20 @@ mod debug_map { } assert_eq!( - "{\"foo\": {\"bar\": true, 10: 10/20}, \ - {\"bar\": true, 10: 10/20}: \"world\"}", + r#"{"foo": {"bar": true, 10: 10/20}, {"bar": true, 10: 10/20}: "world"}"#, format!("{Bar:?}") ); assert_eq!( - "{ - \"foo\": { - \"bar\": true, + r#"{ + "foo": { + "bar": true, 10: 10/20, }, { - \"bar\": true, + "bar": true, 10: 10/20, - }: \"world\", -}", + }: "world", +}"#, format!("{Bar:#?}") ); } @@ -471,6 +544,103 @@ mod debug_map { let _ = format!("{Foo:?}"); } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().finish_non_exhaustive() + } + } + + assert_eq!("{..}", format!("{Foo:?}")); + assert_eq!("{..}", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Entry; + + impl fmt::Debug for Entry { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10, &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct KeyValue; + + impl fmt::Debug for KeyValue { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .key(&"bar") + .value(&true) + .key(&10) + .value(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!(format!("{Entry:?}"), format!("{KeyValue:?}")); + assert_eq!(format!("{Entry:#?}"), format!("{KeyValue:#?}")); + + assert_eq!(r#"{"bar": true, 10: 10/20, ..}"#, format!("{Entry:?}")); + assert_eq!( + r#"{ + "bar": true, + 10: 10/20, + .. +}"#, + format!("{Entry:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10, &format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().entry(&"foo", &Foo).entry(&Foo, &"world").finish_non_exhaustive() + } + } + + assert_eq!( + r#"{"foo": {"bar": true, 10: 10/20, ..}, {"bar": true, 10: 10/20, ..}: "world", ..}"#, + format!("{Bar:?}") + ); + assert_eq!( + r#"{ + "foo": { + "bar": true, + 10: 10/20, + .. + }, + { + "bar": true, + 10: 10/20, + .. + }: "world", + .. +}"#, + format!("{Bar:#?}") + ); + } } mod debug_set { @@ -547,15 +717,89 @@ mod debug_set { } } - assert_eq!("{{true, 10/20}, \"world\"}", format!("{Bar:?}")); + assert_eq!(r#"{{true, 10/20}, "world"}"#, format!("{Bar:?}")); assert_eq!( - "{ + r#"{ { true, 10/20, }, - \"world\", + "world", +}"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set().finish_non_exhaustive() + } + } + + assert_eq!("{..}", format!("{Foo:?}")); + assert_eq!("{..}", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_and_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("{true, 10/20, ..}", format!("{Foo:?}")); + assert_eq!( + "{ + true, + 10/20, + .. }", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_set().entry(&Foo).entry(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"{{true, 10/20, ..}, "world", ..}"#, format!("{Bar:?}")); + assert_eq!( + r#"{ + { + true, + 10/20, + .. + }, + "world", + .. +}"#, format!("{Bar:#?}") ); } @@ -635,15 +879,89 @@ mod debug_list { } } - assert_eq!("[[true, 10/20], \"world\"]", format!("{Bar:?}")); + assert_eq!(r#"[[true, 10/20], "world"]"#, format!("{Bar:?}")); assert_eq!( - "[ + r#"[ [ true, 10/20, ], - \"world\", + "world", +]"#, + format!("{Bar:#?}") + ); + } + + #[test] + fn test_empty_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list().finish_non_exhaustive() + } + } + + assert_eq!("[..]", format!("{Foo:?}")); + assert_eq!("[..]", format!("{Foo:#?}")); + } + + #[test] + fn test_multiple_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + assert_eq!("[true, 10/20, ..]", format!("{Foo:?}")); + assert_eq!( + "[ + true, + 10/20, + .. ]", + format!("{Foo:#?}") + ); + } + + #[test] + fn test_nested_non_exhaustive() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10, 20)) + .finish_non_exhaustive() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_list().entry(&Foo).entry(&"world").finish_non_exhaustive() + } + } + + assert_eq!(r#"[[true, 10/20, ..], "world", ..]"#, format!("{Bar:?}")); + assert_eq!( + r#"[ + [ + true, + 10/20, + .. + ], + "world", + .. +]"#, format!("{Bar:#?}") ); } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 2f0d03abed3..c205f028dd3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -43,6 +43,7 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] +#![feature(debug_more_non_exhaustive)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] @@ -140,7 +141,6 @@ mod intrinsics; mod io; mod iter; mod lazy; -#[cfg(test)] mod macros; mod manually_drop; mod mem; diff --git a/library/core/tests/num/float_iter_sum_identity.rs b/library/core/tests/num/float_iter_sum_identity.rs new file mode 100644 index 00000000000..6d3224522a8 --- /dev/null +++ b/library/core/tests/num/float_iter_sum_identity.rs @@ -0,0 +1,27 @@ +#[test] +fn f32_ref() { + let x: f32 = -0.0; + let still_x: f32 = [x].iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f32_own() { + let x: f32 = -0.0; + let still_x: f32 = [x].into_iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f64_ref() { + let x: f64 = -0.0; + let still_x: f64 = [x].iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} + +#[test] +fn f64_own() { + let x: f64 = -0.0; + let still_x: f64 = [x].into_iter().sum(); + assert_eq!(1. / x, 1. / still_x) +} diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 165d9a29617..7cd3b54e3f3 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -1,427 +1,424 @@ macro_rules! int_module { ($T:ident) => { - #[cfg(test)] - mod tests { - use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; - - use crate::num; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert_eq!(MIN + MAX + 1, 0); - } + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T::*; - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } + use crate::num; - #[test] - fn test_rem_euclid() { - assert_eq!((-1 as $T).rem_euclid(MIN), MAX); - } + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert_eq!(MIN + MAX + 1, 0); + } - #[test] - pub fn test_abs() { - assert_eq!((1 as $T).abs(), 1 as $T); - assert_eq!((0 as $T).abs(), 0 as $T); - assert_eq!((-1 as $T).abs(), 1 as $T); - } + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } - #[test] - fn test_signum() { - assert_eq!((1 as $T).signum(), 1 as $T); - assert_eq!((0 as $T).signum(), 0 as $T); - assert_eq!((-0 as $T).signum(), 0 as $T); - assert_eq!((-1 as $T).signum(), -1 as $T); - } + #[test] + fn test_rem_euclid() { + assert_eq!((-1 as $T).rem_euclid(MIN), MAX); + } - #[test] - fn test_is_positive() { - assert!((1 as $T).is_positive()); - assert!(!(0 as $T).is_positive()); - assert!(!(-0 as $T).is_positive()); - assert!(!(-1 as $T).is_positive()); - } + #[test] + pub fn test_abs() { + assert_eq!((1 as $T).abs(), 1 as $T); + assert_eq!((0 as $T).abs(), 0 as $T); + assert_eq!((-1 as $T).abs(), 1 as $T); + } - #[test] - fn test_is_negative() { - assert!(!(1 as $T).is_negative()); - assert!(!(0 as $T).is_negative()); - assert!(!(-0 as $T).is_negative()); - assert!((-1 as $T).is_negative()); - } + #[test] + fn test_signum() { + assert_eq!((1 as $T).signum(), 1 as $T); + assert_eq!((0 as $T).signum(), 0 as $T); + assert_eq!((-0 as $T).signum(), 0 as $T); + assert_eq!((-1 as $T).signum(), -1 as $T); + } - #[test] - fn test_bitwise_operators() { - assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); - assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); - assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); - assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); - assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); - assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); - } + #[test] + fn test_is_positive() { + assert!((1 as $T).is_positive()); + assert!(!(0 as $T).is_positive()); + assert!(!(-0 as $T).is_positive()); + assert!(!(-1 as $T).is_positive()); + } - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; + #[test] + fn test_is_negative() { + assert!(!(1 as $T).is_negative()); + assert!(!(0 as $T).is_negative()); + assert!(!(-0 as $T).is_negative()); + assert!((-1 as $T).is_negative()); + } - const _0: $T = 0; - const _1: $T = !0; + #[test] + fn test_bitwise_operators() { + assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); + assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); + assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); + assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); + assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); + assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); + } - #[test] - fn test_count_ones() { - assert_eq!(A.count_ones(), 3); - assert_eq!(B.count_ones(), 2); - assert_eq!(C.count_ones(), 5); - } + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; - #[test] - fn test_count_zeros() { - assert_eq!(A.count_zeros(), $T::BITS - 3); - assert_eq!(B.count_zeros(), $T::BITS - 2); - assert_eq!(C.count_zeros(), $T::BITS - 5); - } + const _0: $T = 0; + const _1: $T = !0; - #[test] - fn test_leading_trailing_ones() { - let a: $T = 0b0101_1111; - assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), $T::BITS - 7); + #[test] + fn test_count_ones() { + assert_eq!(A.count_ones(), 3); + assert_eq!(B.count_ones(), 2); + assert_eq!(C.count_ones(), 5); + } - assert_eq!(a.reverse_bits().leading_ones(), 5); + #[test] + fn test_count_zeros() { + assert_eq!(A.count_zeros(), $T::BITS - 3); + assert_eq!(B.count_zeros(), $T::BITS - 2); + assert_eq!(C.count_zeros(), $T::BITS - 5); + } - assert_eq!(_1.leading_ones(), $T::BITS); - assert_eq!(_1.trailing_ones(), $T::BITS); + #[test] + fn test_leading_trailing_ones() { + let a: $T = 0b0101_1111; + assert_eq!(a.trailing_ones(), 5); + assert_eq!((!a).leading_ones(), $T::BITS - 7); - assert_eq!((_1 << 1).trailing_ones(), 0); - assert_eq!(MAX.leading_ones(), 0); + assert_eq!(a.reverse_bits().leading_ones(), 5); - assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq!(MAX.trailing_ones(), $T::BITS - 1); + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); - assert_eq!(_0.leading_ones(), 0); - assert_eq!(_0.trailing_ones(), 0); + assert_eq!((_1 << 1).trailing_ones(), 0); + assert_eq!(MAX.leading_ones(), 0); - let x: $T = 0b0010_1100; - assert_eq!(x.leading_ones(), 0); - assert_eq!(x.trailing_ones(), 0); - } + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!(MAX.trailing_ones(), $T::BITS - 1); - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // 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. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(128), A); - assert_eq!(B.rotate_left(128), B); - assert_eq!(C.rotate_left(128), C); - } + assert_eq!(_0.leading_ones(), 0); + assert_eq!(_0.trailing_ones(), 0); - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); + let x: $T = 0b0010_1100; + assert_eq!(x.leading_ones(), 0); + assert_eq!(x.trailing_ones(), 0); + } - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // 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. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(128), A); + assert_eq!(B.rotate_left(128), B); + assert_eq!(C.rotate_left(128), C); + } - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } - #[test] - fn test_signed_checked_div() { - assert_eq!((10 as $T).checked_div(2), Some(5)); - assert_eq!((5 as $T).checked_div(0), None); - assert_eq!(isize::MIN.checked_div(-1), None); - } + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } - #[test] - fn test_saturating_abs() { - assert_eq!((0 as $T).saturating_abs(), 0); - assert_eq!((123 as $T).saturating_abs(), 123); - assert_eq!((-123 as $T).saturating_abs(), 123); - assert_eq!((MAX - 2).saturating_abs(), MAX - 2); - assert_eq!((MAX - 1).saturating_abs(), MAX - 1); - assert_eq!(MAX.saturating_abs(), MAX); - assert_eq!((MIN + 2).saturating_abs(), MAX - 1); - assert_eq!((MIN + 1).saturating_abs(), MAX); - assert_eq!(MIN.saturating_abs(), MAX); - } + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } - #[test] - fn test_saturating_neg() { - assert_eq!((0 as $T).saturating_neg(), 0); - assert_eq!((123 as $T).saturating_neg(), -123); - assert_eq!((-123 as $T).saturating_neg(), 123); - assert_eq!((MAX - 2).saturating_neg(), MIN + 3); - assert_eq!((MAX - 1).saturating_neg(), MIN + 2); - assert_eq!(MAX.saturating_neg(), MIN + 1); - assert_eq!((MIN + 2).saturating_neg(), MAX - 1); - assert_eq!((MIN + 1).saturating_neg(), MAX); - assert_eq!(MIN.saturating_neg(), MAX); - } + #[test] + fn test_signed_checked_div() { + assert_eq!((10 as $T).checked_div(2), Some(5)); + assert_eq!((5 as $T).checked_div(0), None); + assert_eq!(isize::MIN.checked_div(-1), None); + } - #[test] - fn test_from_str() { - fn from_str<T: std::str::FromStr>(t: &str) -> Option<T> { - std::str::FromStr::from_str(t).ok() - } - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); - assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); - assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); - assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } + #[test] + fn test_saturating_abs() { + assert_eq!((0 as $T).saturating_abs(), 0); + assert_eq!((123 as $T).saturating_abs(), 123); + assert_eq!((-123 as $T).saturating_abs(), 123); + assert_eq!((MAX - 2).saturating_abs(), MAX - 2); + assert_eq!((MAX - 1).saturating_abs(), MAX - 1); + assert_eq!(MAX.saturating_abs(), MAX); + assert_eq!((MIN + 2).saturating_abs(), MAX - 1); + assert_eq!((MIN + 1).saturating_abs(), MAX); + assert_eq!(MIN.saturating_abs(), MAX); + } - #[test] - fn test_from_str_radix() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); - assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); - assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); - assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); - assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); - assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); - assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); - assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); - assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); - assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); - - assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); - assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); - } + #[test] + fn test_saturating_neg() { + assert_eq!((0 as $T).saturating_neg(), 0); + assert_eq!((123 as $T).saturating_neg(), -123); + assert_eq!((-123 as $T).saturating_neg(), 123); + assert_eq!((MAX - 2).saturating_neg(), MIN + 3); + assert_eq!((MAX - 1).saturating_neg(), MIN + 2); + assert_eq!(MAX.saturating_neg(), MIN + 1); + assert_eq!((MIN + 2).saturating_neg(), MAX - 1); + assert_eq!((MIN + 1).saturating_neg(), MAX); + assert_eq!(MIN.saturating_neg(), MAX); + } - #[test] - fn test_pow() { - let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); - - r = MAX; - // use `^` to represent .pow() with no overflow. - // if itest::MAX == 2^j-1, then itest is a `j` bit int, - // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, - // thussaturating_pow the overflowing result is exactly 1. - assert_eq!(r.wrapping_pow(2), 1 as $T); - assert_eq!(r.checked_pow(2), None); - assert_eq!(r.overflowing_pow(2), (1 as $T, true)); - assert_eq!(r.saturating_pow(2), MAX); - //test for negative exponent. - r = -2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(3), -8 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(3), -8 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(3), Some(-8 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(3), -8 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); + #[test] + fn test_from_str() { + fn from_str<T: std::str::FromStr>(t: &str) -> Option<T> { + std::str::FromStr::from_str(t).ok() } + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); + assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); + assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); + assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } - #[test] - fn test_isqrt() { - assert_eq!($T::MIN.checked_isqrt(), None); - assert_eq!((-1 as $T).checked_isqrt(), None); - assert_eq!((0 as $T).isqrt(), 0 as $T); - assert_eq!((1 as $T).isqrt(), 1 as $T); - assert_eq!((2 as $T).isqrt(), 1 as $T); - assert_eq!((99 as $T).isqrt(), 9 as $T); - assert_eq!((100 as $T).isqrt(), 10 as $T); - } + #[test] + fn test_from_str_radix() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); + assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); + assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); + assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); + assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); + assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); + assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); + assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); + assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); + assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); + + assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); + assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); + } - #[cfg(not(miri))] // Miri is too slow - #[test] - fn test_lots_of_isqrt() { - let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; - for n in 0..=n_max { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - - for n in ($T::MAX - 127)..=$T::MAX { - let isqrt: $T = n.isqrt(); - - assert!(isqrt.pow(2) <= n); - let (square, overflow) = (isqrt + 1).overflowing_pow(2); - assert!(overflow || square > n); - } - } + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + //test for negative exponent. + r = -2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(3), -8 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(3), -8 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(3), Some(-8 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(3), (-8 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(3), -8 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + } - #[test] - fn test_div_floor() { - let a: $T = 8; - let b = 3; - assert_eq!(a.div_floor(b), 2); - assert_eq!(a.div_floor(-b), -3); - assert_eq!((-a).div_floor(b), -3); - assert_eq!((-a).div_floor(-b), 2); - } + #[test] + fn test_isqrt() { + assert_eq!($T::MIN.checked_isqrt(), None); + assert_eq!((-1 as $T).checked_isqrt(), None); + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + } - #[test] - fn test_div_ceil() { - let a: $T = 8; - let b = 3; - assert_eq!(a.div_ceil(b), 3); - assert_eq!(a.div_ceil(-b), -2); - assert_eq!((-a).div_ceil(b), -2); - assert_eq!((-a).div_ceil(-b), 3); - } + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); - #[test] - fn test_next_multiple_of() { - assert_eq!((16 as $T).next_multiple_of(8), 16); - assert_eq!((23 as $T).next_multiple_of(8), 24); - assert_eq!((16 as $T).next_multiple_of(-8), 16); - assert_eq!((23 as $T).next_multiple_of(-8), 16); - assert_eq!((-16 as $T).next_multiple_of(8), -16); - assert_eq!((-23 as $T).next_multiple_of(8), -16); - assert_eq!((-16 as $T).next_multiple_of(-8), -16); - assert_eq!((-23 as $T).next_multiple_of(-8), -24); - assert_eq!(MIN.next_multiple_of(-1), MIN); + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); } - #[test] - fn test_checked_next_multiple_of() { - assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16)); - assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24)); - assert_eq!((1 as $T).checked_next_multiple_of(0), None); - assert_eq!(MAX.checked_next_multiple_of(2), None); - assert_eq!(MIN.checked_next_multiple_of(-3), None); - assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN)); - } + for n in ($T::MAX - 127)..=$T::MAX { + let isqrt: $T = n.isqrt(); - #[test] - fn test_carrying_add() { - assert_eq!($T::MAX.carrying_add(1, false), ($T::MIN, true)); - assert_eq!($T::MAX.carrying_add(0, true), ($T::MIN, true)); - assert_eq!($T::MAX.carrying_add(1, true), ($T::MIN + 1, true)); - assert_eq!($T::MAX.carrying_add(-1, false), ($T::MAX - 1, false)); - assert_eq!($T::MAX.carrying_add(-1, true), ($T::MAX, false)); // no intermediate overflow - assert_eq!($T::MIN.carrying_add(-1, false), ($T::MAX, true)); - assert_eq!($T::MIN.carrying_add(-1, true), ($T::MIN, false)); // no intermediate overflow - assert_eq!((0 as $T).carrying_add($T::MAX, true), ($T::MIN, true)); - assert_eq!((0 as $T).carrying_add($T::MIN, true), ($T::MIN + 1, false)); + assert!(isqrt.pow(2) <= n); + let (square, overflow) = (isqrt + 1).overflowing_pow(2); + assert!(overflow || square > n); } + } - #[test] - fn test_borrowing_sub() { - assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); - assert_eq!($T::MIN.borrowing_sub(-1, false), ($T::MIN + 1, false)); - assert_eq!($T::MIN.borrowing_sub(-1, true), ($T::MIN, false)); // no intermediate overflow - assert_eq!($T::MAX.borrowing_sub(-1, false), ($T::MIN, true)); - assert_eq!($T::MAX.borrowing_sub(-1, true), ($T::MAX, false)); // no intermediate overflow - assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true)); - assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false)); - } + #[test] + fn test_div_floor() { + let a: $T = 8; + let b = 3; + assert_eq!(a.div_floor(b), 2); + assert_eq!(a.div_floor(-b), -3); + assert_eq!((-a).div_floor(b), -3); + assert_eq!((-a).div_floor(-b), 2); + } - #[test] - fn test_midpoint() { - assert_eq!(<$T>::midpoint(1, 3), 2); - assert_eq!(<$T>::midpoint(3, 1), 2); - - assert_eq!(<$T>::midpoint(0, 0), 0); - assert_eq!(<$T>::midpoint(0, 2), 1); - assert_eq!(<$T>::midpoint(2, 0), 1); - assert_eq!(<$T>::midpoint(2, 2), 2); - - assert_eq!(<$T>::midpoint(1, 4), 2); - assert_eq!(<$T>::midpoint(4, 1), 2); - assert_eq!(<$T>::midpoint(3, 4), 3); - assert_eq!(<$T>::midpoint(4, 3), 3); - - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1); - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - - assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); - } + #[test] + fn test_div_ceil() { + let a: $T = 8; + let b = 3; + assert_eq!(a.div_ceil(b), 3); + assert_eq!(a.div_ceil(-b), -2); + assert_eq!((-a).div_ceil(b), -2); + assert_eq!((-a).div_ceil(-b), 3); + } + + #[test] + fn test_next_multiple_of() { + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!((16 as $T).next_multiple_of(-8), 16); + assert_eq!((23 as $T).next_multiple_of(-8), 16); + assert_eq!((-16 as $T).next_multiple_of(8), -16); + assert_eq!((-23 as $T).next_multiple_of(8), -16); + assert_eq!((-16 as $T).next_multiple_of(-8), -16); + assert_eq!((-23 as $T).next_multiple_of(-8), -24); + assert_eq!(MIN.next_multiple_of(-1), MIN); + } + + #[test] + fn test_checked_next_multiple_of() { + assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16)); + assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24)); + assert_eq!((1 as $T).checked_next_multiple_of(0), None); + assert_eq!(MAX.checked_next_multiple_of(2), None); + assert_eq!(MIN.checked_next_multiple_of(-3), None); + assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN)); + } + + #[test] + fn test_carrying_add() { + assert_eq!($T::MAX.carrying_add(1, false), ($T::MIN, true)); + assert_eq!($T::MAX.carrying_add(0, true), ($T::MIN, true)); + assert_eq!($T::MAX.carrying_add(1, true), ($T::MIN + 1, true)); + assert_eq!($T::MAX.carrying_add(-1, false), ($T::MAX - 1, false)); + assert_eq!($T::MAX.carrying_add(-1, true), ($T::MAX, false)); // no intermediate overflow + assert_eq!($T::MIN.carrying_add(-1, false), ($T::MAX, true)); + assert_eq!($T::MIN.carrying_add(-1, true), ($T::MIN, false)); // no intermediate overflow + assert_eq!((0 as $T).carrying_add($T::MAX, true), ($T::MIN, true)); + assert_eq!((0 as $T).carrying_add($T::MIN, true), ($T::MIN + 1, false)); + } + + #[test] + fn test_borrowing_sub() { + assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); + assert_eq!($T::MIN.borrowing_sub(-1, false), ($T::MIN + 1, false)); + assert_eq!($T::MIN.borrowing_sub(-1, true), ($T::MIN, false)); // no intermediate overflow + assert_eq!($T::MAX.borrowing_sub(-1, false), ($T::MIN, true)); + assert_eq!($T::MAX.borrowing_sub(-1, true), ($T::MAX, false)); // no intermediate overflow + assert_eq!((0 as $T).borrowing_sub($T::MIN, false), ($T::MIN, true)); + assert_eq!((0 as $T).borrowing_sub($T::MIN, true), ($T::MAX, false)); + } + + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); + + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); + + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); + + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), -1); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), -1); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); } }; } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 9d2912c4b22..dad46ad88fe 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -30,6 +30,7 @@ mod int_log; mod ops; mod wrapping; +mod float_iter_sum_identity; mod ieee754; mod nan; @@ -177,7 +178,7 @@ fn test_can_not_overflow() { // Check u128 separately: for base in 2..=36 { - let num = u128::MAX as u128; + let num = <u128>::MAX; let max_len_string = format_radix(num, base as u128); // base 16 fits perfectly for u128 and won't overflow: assert_eq!(can_overflow::<u128>(base, &max_len_string), base != 16); diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index d009ad89d5c..f4fa789461e 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -1,320 +1,317 @@ macro_rules! uint_module { ($T:ident) => { - #[cfg(test)] - mod tests { - use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; - use std::str::FromStr; - - use crate::num; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!((MIN + MAX).wrapping_add(1) == 0); - } + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T::*; + use std::str::FromStr; - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } + use crate::num; - #[test] - fn test_bitwise_operators() { - assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); - assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); - assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); - assert!(0b1110 as $T == (0b0111 as $T).shl(1)); - assert!(0b0111 as $T == (0b1110 as $T).shr(1)); - assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); - } + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert!((MIN + MAX).wrapping_add(1) == 0); + } - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } - const _0: $T = 0; - const _1: $T = !0; + #[test] + fn test_bitwise_operators() { + assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); + assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); + assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); + assert!(0b1110 as $T == (0b0111 as $T).shl(1)); + assert!(0b0111 as $T == (0b1110 as $T).shr(1)); + assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); + } - #[test] - fn test_count_ones() { - assert!(A.count_ones() == 3); - assert!(B.count_ones() == 2); - assert!(C.count_ones() == 5); - } + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; - #[test] - fn test_count_zeros() { - assert!(A.count_zeros() == $T::BITS - 3); - assert!(B.count_zeros() == $T::BITS - 2); - assert!(C.count_zeros() == $T::BITS - 5); - } + const _0: $T = 0; + const _1: $T = !0; - #[test] - fn test_leading_trailing_ones() { - let a: $T = 0b0101_1111; - assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), $T::BITS - 7); + #[test] + fn test_count_ones() { + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); + } - assert_eq!(a.reverse_bits().leading_ones(), 5); + #[test] + fn test_count_zeros() { + assert!(A.count_zeros() == $T::BITS - 3); + assert!(B.count_zeros() == $T::BITS - 2); + assert!(C.count_zeros() == $T::BITS - 5); + } - assert_eq!(_1.leading_ones(), $T::BITS); - assert_eq!(_1.trailing_ones(), $T::BITS); + #[test] + fn test_leading_trailing_ones() { + let a: $T = 0b0101_1111; + assert_eq!(a.trailing_ones(), 5); + assert_eq!((!a).leading_ones(), $T::BITS - 7); - assert_eq!((_1 << 1).trailing_ones(), 0); - assert_eq!((_1 >> 1).leading_ones(), 0); + assert_eq!(a.reverse_bits().leading_ones(), 5); - assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1); + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); - assert_eq!(_0.leading_ones(), 0); - assert_eq!(_0.trailing_ones(), 0); + assert_eq!((_1 << 1).trailing_ones(), 0); + assert_eq!((_1 >> 1).leading_ones(), 0); - let x: $T = 0b0010_1100; - assert_eq!(x.leading_ones(), 0); - assert_eq!(x.trailing_ones(), 0); - } + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1); - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // 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. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(128), A); - assert_eq!(B.rotate_left(128), B); - assert_eq!(C.rotate_left(128), C); - } + assert_eq!(_0.leading_ones(), 0); + assert_eq!(_0.trailing_ones(), 0); - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); + let x: $T = 0b0010_1100; + assert_eq!(x.leading_ones(), 0); + assert_eq!(x.trailing_ones(), 0); + } - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // 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. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(128), A); + assert_eq!(B.rotate_left(128), B); + assert_eq!(C.rotate_left(128), C); + } - #[test] - fn test_reverse_bits() { - assert_eq!(A.reverse_bits().reverse_bits(), A); - assert_eq!(B.reverse_bits().reverse_bits(), B); - assert_eq!(C.reverse_bits().reverse_bits(), C); + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); - // Swapping these should make no difference - assert_eq!(_0.reverse_bits(), _0); - assert_eq!(_1.reverse_bits(), _1); - } + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } + #[test] + fn test_reverse_bits() { + assert_eq!(A.reverse_bits().reverse_bits(), A); + assert_eq!(B.reverse_bits().reverse_bits(), B); + assert_eq!(C.reverse_bits().reverse_bits(), C); - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } + // Swapping these should make no difference + assert_eq!(_0.reverse_bits(), _0); + assert_eq!(_1.reverse_bits(), _1); + } - #[test] - fn test_unsigned_checked_div() { - assert!((10 as $T).checked_div(2) == Some(5)); - assert!((5 as $T).checked_div(0) == None); - } + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } - fn from_str<T: FromStr>(t: &str) -> Option<T> { - FromStr::from_str(t).ok() - } + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } - #[test] - pub fn test_from_str() { - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } + #[test] + fn test_unsigned_checked_div() { + assert!((10 as $T).checked_div(2) == Some(5)); + assert!((5 as $T).checked_div(0) == None); + } - #[test] - pub fn test_parse_bytes() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); - assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); - assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); - } + fn from_str<T: FromStr>(t: &str) -> Option<T> { + FromStr::from_str(t).ok() + } - #[test] - fn test_pow() { - let mut r = 2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(0), 1 as $T); - assert_eq!(r.wrapping_pow(2), 4 as $T); - assert_eq!(r.wrapping_pow(0), 1 as $T); - assert_eq!(r.checked_pow(2), Some(4 as $T)); - assert_eq!(r.checked_pow(0), Some(1 as $T)); - assert_eq!(r.overflowing_pow(2), (4 as $T, false)); - assert_eq!(r.overflowing_pow(0), (1 as $T, false)); - assert_eq!(r.saturating_pow(2), 4 as $T); - assert_eq!(r.saturating_pow(0), 1 as $T); - - r = MAX; - // use `^` to represent .pow() with no overflow. - // if itest::MAX == 2^j-1, then itest is a `j` bit int, - // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, - // thussaturating_pow the overflowing result is exactly 1. - assert_eq!(r.wrapping_pow(2), 1 as $T); - assert_eq!(r.checked_pow(2), None); - assert_eq!(r.overflowing_pow(2), (1 as $T, true)); - assert_eq!(r.saturating_pow(2), MAX); - } + #[test] + pub fn test_from_str() { + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } - #[test] - fn test_isqrt() { - assert_eq!((0 as $T).isqrt(), 0 as $T); - assert_eq!((1 as $T).isqrt(), 1 as $T); - assert_eq!((2 as $T).isqrt(), 1 as $T); - assert_eq!((99 as $T).isqrt(), 9 as $T); - assert_eq!((100 as $T).isqrt(), 10 as $T); - assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); - } + #[test] + pub fn test_parse_bytes() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); + assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); + assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); + } - #[cfg(not(miri))] // Miri is too slow - #[test] - fn test_lots_of_isqrt() { - let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; - for n in 0..=n_max { - let isqrt: $T = n.isqrt(); + #[test] + fn test_pow() { + let mut r = 2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + assert_eq!(r.wrapping_pow(2), 4 as $T); + assert_eq!(r.wrapping_pow(0), 1 as $T); + assert_eq!(r.checked_pow(2), Some(4 as $T)); + assert_eq!(r.checked_pow(0), Some(1 as $T)); + assert_eq!(r.overflowing_pow(2), (4 as $T, false)); + assert_eq!(r.overflowing_pow(0), (1 as $T, false)); + assert_eq!(r.saturating_pow(2), 4 as $T); + assert_eq!(r.saturating_pow(0), 1 as $T); + + r = MAX; + // use `^` to represent .pow() with no overflow. + // if itest::MAX == 2^j-1, then itest is a `j` bit int, + // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, + // thussaturating_pow the overflowing result is exactly 1. + assert_eq!(r.wrapping_pow(2), 1 as $T); + assert_eq!(r.checked_pow(2), None); + assert_eq!(r.overflowing_pow(2), (1 as $T, true)); + assert_eq!(r.saturating_pow(2), MAX); + } - assert!(isqrt.pow(2) <= n); - assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); - } + #[test] + fn test_isqrt() { + assert_eq!((0 as $T).isqrt(), 0 as $T); + assert_eq!((1 as $T).isqrt(), 1 as $T); + assert_eq!((2 as $T).isqrt(), 1 as $T); + assert_eq!((99 as $T).isqrt(), 9 as $T); + assert_eq!((100 as $T).isqrt(), 10 as $T); + assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); + } - for n in ($T::MAX - 255)..=$T::MAX { - let isqrt: $T = n.isqrt(); + #[cfg(not(miri))] // Miri is too slow + #[test] + fn test_lots_of_isqrt() { + let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T; + for n in 0..=n_max { + let isqrt: $T = n.isqrt(); - assert!(isqrt.pow(2) <= n); - assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); - } + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); } - #[test] - fn test_div_floor() { - assert_eq!((8 as $T).div_floor(3), 2); - } + for n in ($T::MAX - 255)..=$T::MAX { + let isqrt: $T = n.isqrt(); - #[test] - fn test_div_ceil() { - assert_eq!((8 as $T).div_ceil(3), 3); + assert!(isqrt.pow(2) <= n); + assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n); } + } - #[test] - fn test_next_multiple_of() { - assert_eq!((16 as $T).next_multiple_of(8), 16); - assert_eq!((23 as $T).next_multiple_of(8), 24); - assert_eq!(MAX.next_multiple_of(1), MAX); - } + #[test] + fn test_div_floor() { + assert_eq!((8 as $T).div_floor(3), 2); + } - #[test] - fn test_checked_next_multiple_of() { - assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq!((1 as $T).checked_next_multiple_of(0), None); - assert_eq!(MAX.checked_next_multiple_of(2), None); - } + #[test] + fn test_div_ceil() { + assert_eq!((8 as $T).div_ceil(3), 3); + } - #[test] - fn test_is_next_multiple_of() { - assert!((12 as $T).is_multiple_of(4)); - assert!(!(12 as $T).is_multiple_of(5)); - assert!((0 as $T).is_multiple_of(0)); - assert!(!(12 as $T).is_multiple_of(0)); - } + #[test] + fn test_next_multiple_of() { + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!(MAX.next_multiple_of(1), MAX); + } - #[test] - fn test_carrying_add() { - assert_eq!($T::MAX.carrying_add(1, false), (0, true)); - assert_eq!($T::MAX.carrying_add(0, true), (0, true)); - assert_eq!($T::MAX.carrying_add(1, true), (1, true)); + #[test] + fn test_checked_next_multiple_of() { + assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq!((1 as $T).checked_next_multiple_of(0), None); + assert_eq!(MAX.checked_next_multiple_of(2), None); + } - assert_eq!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); - assert_eq!($T::MIN.carrying_add(0, true), (1, false)); - assert_eq!($T::MIN.carrying_add($T::MAX, true), (0, true)); - } + #[test] + fn test_is_next_multiple_of() { + assert!((12 as $T).is_multiple_of(4)); + assert!(!(12 as $T).is_multiple_of(5)); + assert!((0 as $T).is_multiple_of(0)); + assert!(!(12 as $T).is_multiple_of(0)); + } - #[test] - fn test_borrowing_sub() { - assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); - assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); + #[test] + fn test_carrying_add() { + assert_eq!($T::MAX.carrying_add(1, false), (0, true)); + assert_eq!($T::MAX.carrying_add(0, true), (0, true)); + assert_eq!($T::MAX.carrying_add(1, true), (1, true)); - assert_eq!($T::MAX.borrowing_sub($T::MAX, false), (0, false)); - assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); - assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); - } + assert_eq!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); + assert_eq!($T::MIN.carrying_add(0, true), (1, false)); + assert_eq!($T::MIN.carrying_add($T::MAX, true), (0, true)); + } - #[test] - fn test_midpoint() { - assert_eq!(<$T>::midpoint(1, 3), 2); - assert_eq!(<$T>::midpoint(3, 1), 2); - - assert_eq!(<$T>::midpoint(0, 0), 0); - assert_eq!(<$T>::midpoint(0, 2), 1); - assert_eq!(<$T>::midpoint(2, 0), 1); - assert_eq!(<$T>::midpoint(2, 2), 2); - - assert_eq!(<$T>::midpoint(1, 4), 2); - assert_eq!(<$T>::midpoint(4, 1), 2); - assert_eq!(<$T>::midpoint(3, 4), 3); - assert_eq!(<$T>::midpoint(4, 3), 3); - - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - - assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); - assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); - } + #[test] + fn test_borrowing_sub() { + assert_eq!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); + assert_eq!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); + + assert_eq!($T::MAX.borrowing_sub($T::MAX, false), (0, false)); + assert_eq!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); + assert_eq!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); + } + + #[test] + fn test_midpoint() { + assert_eq!(<$T>::midpoint(1, 3), 2); + assert_eq!(<$T>::midpoint(3, 1), 2); + + assert_eq!(<$T>::midpoint(0, 0), 0); + assert_eq!(<$T>::midpoint(0, 2), 1); + assert_eq!(<$T>::midpoint(2, 0), 1); + assert_eq!(<$T>::midpoint(2, 2), 2); + + assert_eq!(<$T>::midpoint(1, 4), 2); + assert_eq!(<$T>::midpoint(4, 1), 2); + assert_eq!(<$T>::midpoint(3, 4), 3); + assert_eq!(<$T>::midpoint(4, 3), 3); + + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + + assert_eq!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); + assert_eq!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); } }; } diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index 9d1c1ba305b..c1e0e5c1c89 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -3,7 +3,7 @@ //! See the build.rs for libcompiler_builtins crate for details. use std::env; -use std::path::Path; +use std::path::PathBuf; fn main() { println!("cargo:rerun-if-env-changed=LLVM_PROFILER_RT_LIB"); @@ -79,17 +79,25 @@ fn main() { cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); } - // Note that this should exist if we're going to run (otherwise we just - // don't build profiler builtins at all). - let root = Path::new("../../src/llvm-project/compiler-rt"); + // Get the LLVM `compiler-rt` directory from bootstrap. + println!("cargo:rerun-if-env-changed=RUST_COMPILER_RT_FOR_PROFILER"); + let root = PathBuf::from(env::var("RUST_COMPILER_RT_FOR_PROFILER").unwrap_or_else(|_| { + let path = "../../src/llvm-project/compiler-rt"; + println!("RUST_COMPILER_RT_FOR_PROFILER was not set; falling back to {path:?}"); + path.to_owned() + })); let src_root = root.join("lib").join("profile"); + assert!(src_root.exists(), "profiler runtime source directory not found: {src_root:?}"); + let mut n_sources_found = 0u32; for src in profile_sources { let path = src_root.join(src); if path.exists() { cfg.file(path); + n_sources_found += 1; } } + assert!(n_sources_found > 0, "couldn't find any profiler runtime source files in {src_root:?}"); cfg.include(root.join("include")); cfg.warnings(false); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 7f23681ee45..334c75df231 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.118" } +compiler_builtins = { version = "0.1.121" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ diff --git a/library/std/build.rs b/library/std/build.rs index 35a5977b6eb..fecdf2c3e1f 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -103,9 +103,9 @@ fn main() { ("arm64ec", _) => false, // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054> ("x86_64", "windows") => false, - // x86 has ABI bugs that show up with optimizations. This should be partially fixed with - // the compiler-builtins update. <https://github.com/rust-lang/rust/issues/123885> - ("x86" | "x86_64", _) => false, + // Apple has a special ABI for `f16` that we do not yet support + // FIXME(builtins): fixed by <https://github.com/rust-lang/compiler-builtins/pull/675> + ("x86" | "x86_64", _) if target_vendor == "apple" => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` ("powerpc" | "powerpc64", _) => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` @@ -140,17 +140,17 @@ fn main() { _ => false, }; - // These are currently empty, but will fill up as some platforms move from completely - // unreliable to reliable basics but unreliable math. + // Configure platforms that have reliable basics but may have unreliable math. // LLVM is currenlty adding missing routines, <https://github.com/llvm/llvm-project/issues/93566> let has_reliable_f16_math = has_reliable_f16 && match (target_arch.as_str(), target_os.as_str()) { // FIXME: Disabled on Miri as the intrinsics are not implemented yet. _ if is_miri => false, - // Currently nothing special. Hooray! - // This will change as platforms gain better better support for standard ops but math - // lags behind. + // x86 has a crash for `powi`: <https://github.com/llvm/llvm-project/issues/105747> + ("x86" | "x86_64", _) => false, + // Assume that working `f16` means working `f16` math for most platforms, since + // operations just go through `f32`. _ => true, }; diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index f6df6259137..506d708d0d2 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -248,11 +248,11 @@ impl f128 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f128) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations + /// is not generally guaranteed. See [specification of NaN bit + /// patterns](primitive@f32#nan-bit-patterns) for more info. /// /// # Examples /// diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 10908332762..033a3d45009 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -247,11 +247,11 @@ impl f16 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f16) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations + /// is not generally guaranteed. See [specification of NaN bit + /// patterns](primitive@f32#nan-bit-patterns) for more info. /// /// # Examples /// diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 12433d25bfa..35c2a77b533 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -226,11 +226,11 @@ impl f32 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f32) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations + /// is not generally guaranteed. See [specification of NaN bit + /// patterns](primitive@f32#nan-bit-patterns) for more info. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index a343e19173e..c177f74a97e 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -226,11 +226,11 @@ impl f64 { /// Returns a number composed of the magnitude of `self` and the sign of /// `sign`. /// - /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise - /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of - /// `sign` is returned. Note, however, that conserving the sign bit on NaN - /// across arithmetical operations is not generally guaranteed. - /// See [explanation of NaN as a special value](primitive@f32) for more info. + /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. + /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is + /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations + /// is not generally guaranteed. See [specification of NaN bit + /// patterns](primitive@f32#nan-bit-patterns) for more info. /// /// # Examples /// diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c5edb03bb08..6a0d9f47960 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2491,6 +2491,8 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// Consider ignoring the error if validating the removal is not required for your use case. /// +/// [`io::ErrorKind::NotFound`] is only returned if no removal occurs. +/// /// [`fs::remove_file`]: remove_file /// [`fs::remove_dir`]: remove_dir /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2530a376387..f65e9bc8d8b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -363,6 +363,7 @@ #![feature(get_mut_unchecked)] #![feature(map_try_insert)] #![feature(new_uninit)] +#![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] #![feature(thin_box)] #![feature(try_reserve_kind)] diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index a58ca543d67..9ec3e387e2b 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -2,7 +2,6 @@ //! //! [`std::fs`]: crate::fs -#![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] // Used for `File::read` on intra-doc links diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index e36b93e60ea..33b50c9e53b 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -30,7 +30,7 @@ #![cfg_attr(not(target_env = "p2"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(target_env = "p2", unstable(feature = "wasip2", issue = "none"))] -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] #![doc(cfg(target_os = "wasi"))] pub mod ffi; diff --git a/library/std/src/os/wasip2/mod.rs b/library/std/src/os/wasip2/mod.rs index 1d44dd72814..809a288f20d 100644 --- a/library/std/src/os/wasip2/mod.rs +++ b/library/std/src/os/wasip2/mod.rs @@ -2,4 +2,5 @@ //! //! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. +#![forbid(unsafe_op_in_unsafe_fn)] #![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index e818b448270..190eed94555 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -275,7 +275,7 @@ fn default_hook(info: &PanicHookInfo<'_>) { if cfg!(miri) { let _ = writeln!( err, - "note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` \ + "note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \ for the environment variable to have an effect" ); } diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9ffdebe1b6f..bbea27ebc10 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2296,6 +2296,15 @@ impl Child { /// } /// ``` /// +/// In its current implementation, this function will execute exit handlers registered with `atexit` +/// as well as other platform-specific exit handlers (e.g. `fini` sections of ELF shared objects). +/// This means that Rust requires that all exit handlers are safe to execute at any time. In +/// particular, if an exit handler cleans up some state that might be concurrently accessed by other +/// threads, it is required that the exit handler performs suitable synchronization with those +/// threads. (The alternative to this requirement would be to not run exit handlers at all, which is +/// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an +/// unsafe operation is not an option.) +/// /// ## Platform-specific behavior /// /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/alloc/hermit.rs index f10d5f9227e..77f8200a70a 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/alloc/hermit.rs @@ -1,4 +1,3 @@ -use super::hermit_abi; use crate::alloc::{GlobalAlloc, Layout, System}; #[stable(feature = "alloc_system_type", since = "1.28.0")] diff --git a/library/std/src/sys/pal/common/alloc.rs b/library/std/src/sys/alloc/mod.rs index 1b465f95d1b..2c0b533a570 100644 --- a/library/std/src/sys/pal/common/alloc.rs +++ b/library/std/src/sys/alloc/mod.rs @@ -1,10 +1,18 @@ #![forbid(unsafe_op_in_unsafe_fn)] + use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::{cmp, ptr}; +use crate::ptr; // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. -#[cfg(any( +#[allow(dead_code)] +const MIN_ALIGN: usize = if cfg!(any( + all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")), + all(target_arch = "xtensa", target_os = "espidf"), +)) { + // The allocator on the esp-idf and zkvm platforms guarantees 4 byte alignment. + 4 +} else if cfg!(any( target_arch = "x86", target_arch = "arm", target_arch = "m68k", @@ -16,11 +24,11 @@ use crate::{cmp, ptr}; target_arch = "sparc", target_arch = "wasm32", target_arch = "hexagon", - all(target_arch = "riscv32", not(any(target_os = "espidf", target_os = "zkvm"))), - all(target_arch = "xtensa", not(target_os = "espidf")), -))] -pub const MIN_ALIGN: usize = 8; -#[cfg(any( + target_arch = "riscv32", + target_arch = "xtensa", +)) { + 8 +} else if cfg!(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec", @@ -31,16 +39,14 @@ pub const MIN_ALIGN: usize = 8; target_arch = "sparc64", target_arch = "riscv64", target_arch = "wasm64", -))] -pub const MIN_ALIGN: usize = 16; -// The allocator on the esp-idf and zkvm platforms guarantee 4 byte alignment. -#[cfg(all(any( - all(target_arch = "riscv32", any(target_os = "espidf", target_os = "zkvm")), - all(target_arch = "xtensa", target_os = "espidf"), -)))] -pub const MIN_ALIGN: usize = 4; +)) { + 16 +} else { + panic!("add a value for MIN_ALIGN") +}; -pub unsafe fn realloc_fallback( +#[allow(dead_code)] +unsafe fn realloc_fallback( alloc: &System, ptr: *mut u8, old_layout: Layout, @@ -52,10 +58,37 @@ pub unsafe fn realloc_fallback( let new_ptr = GlobalAlloc::alloc(alloc, new_layout); if !new_ptr.is_null() { - let size = cmp::min(old_layout.size(), new_size); + let size = usize::min(old_layout.size(), new_size); ptr::copy_nonoverlapping(ptr, new_ptr, size); GlobalAlloc::dealloc(alloc, ptr, old_layout); } + new_ptr } } + +cfg_if::cfg_if! { + if #[cfg(any( + target_family = "unix", + target_os = "wasi", + target_os = "teeos", + ))] { + mod unix; + } else if #[cfg(target_os = "windows")] { + mod windows; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + } else if #[cfg(target_family = "wasm")] { + mod wasm; + } else if #[cfg(target_os = "xous")] { + mod xous; + } else if #[cfg(target_os = "zkvm")] { + mod zkvm; + } +} diff --git a/library/std/src/sys/pal/sgx/alloc.rs b/library/std/src/sys/alloc/sgx.rs index f68ede9fcf0..fca9d087e5b 100644 --- a/library/std/src/sys/pal/sgx/alloc.rs +++ b/library/std/src/sys/alloc/sgx.rs @@ -1,9 +1,8 @@ -use core::sync::atomic::{AtomicBool, Ordering}; - -use super::abi::mem as sgx_mem; -use super::waitqueue::SpinMutex; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; +use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sys::pal::abi::mem as sgx_mem; +use crate::sys::pal::waitqueue::SpinMutex; // Using a SpinMutex because we never want to exit the enclave waiting for the // allocator. diff --git a/library/std/src/sys/pal/solid/alloc.rs b/library/std/src/sys/alloc/solid.rs index 4cf60ac9b2e..abb534a1c5c 100644 --- a/library/std/src/sys/pal/solid/alloc.rs +++ b/library/std/src/sys/alloc/solid.rs @@ -1,5 +1,5 @@ +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/pal/uefi/alloc.rs b/library/std/src/sys/alloc/uefi.rs index 15404ac3ea6..5221876e908 100644 --- a/library/std/src/sys/pal/uefi/alloc.rs +++ b/library/std/src/sys/alloc/uefi.rs @@ -3,9 +3,9 @@ use r_efi::protocols::loaded_image; -use super::helpers; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::sync::OnceLock; +use crate::sys::pal::helpers; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/alloc/unix.rs index 625ba5247f1..46ed7de7162 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/alloc/unix.rs @@ -1,6 +1,6 @@ +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { @@ -11,7 +11,7 @@ unsafe impl GlobalAlloc for System { // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::malloc(layout.size()) as *mut u8 + unsafe { libc::malloc(layout.size()) as *mut u8 } } else { // `posix_memalign` returns a non-aligned value if supplied a very // large alignment on older versions of Apple's platforms (unknown @@ -25,7 +25,7 @@ unsafe impl GlobalAlloc for System { return ptr::null_mut(); } } - aligned_malloc(&layout) + unsafe { aligned_malloc(&layout) } } } @@ -33,11 +33,11 @@ unsafe impl GlobalAlloc for System { unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { // See the comment above in `alloc` for why this check looks the way it does. if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - libc::calloc(layout.size(), 1) as *mut u8 + unsafe { libc::calloc(layout.size(), 1) as *mut u8 } } else { - let ptr = self.alloc(layout); + let ptr = unsafe { self.alloc(layout) }; if !ptr.is_null() { - ptr::write_bytes(ptr, 0, layout.size()); + unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; } ptr } @@ -45,15 +45,15 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - libc::free(ptr as *mut libc::c_void) + unsafe { libc::free(ptr as *mut libc::c_void) } } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } } else { - realloc_fallback(self, ptr, layout, new_size) + unsafe { realloc_fallback(self, ptr, layout, new_size) } } } } @@ -81,7 +81,7 @@ cfg_if::cfg_if! { // posix_memalign only has one, clear requirement: that the alignment be a multiple of // `sizeof(void*)`. Since these are all powers of 2, we can just use max. let align = layout.align().max(crate::mem::size_of::<usize>()); - let ret = libc::posix_memalign(&mut out, align, layout.size()); + let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) }; if ret != 0 { ptr::null_mut() } else { out as *mut u8 } } } diff --git a/library/std/src/sys/pal/wasm/alloc.rs b/library/std/src/sys/alloc/wasm.rs index ef9d753d7f8..ef9d753d7f8 100644 --- a/library/std/src/sys/pal/wasm/alloc.rs +++ b/library/std/src/sys/alloc/wasm.rs diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/alloc/windows.rs index 2205885687d..e91956966aa 100644 --- a/library/std/src/sys/pal/windows/alloc.rs +++ b/library/std/src/sys/alloc/windows.rs @@ -1,11 +1,10 @@ -use core::mem::MaybeUninit; - +use super::{realloc_fallback, MIN_ALIGN}; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ffi::c_void; +use crate::mem::MaybeUninit; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sys::c; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; #[cfg(test)] mod tests; @@ -113,28 +112,28 @@ fn init_or_get_process_heap() -> c::HANDLE { extern "C" fn process_heap_init_and_alloc( _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc` flags: u32, - dwBytes: usize, + bytes: usize, ) -> *mut c_void { let heap = init_or_get_process_heap(); if core::intrinsics::unlikely(heap.is_null()) { return ptr::null_mut(); } // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, dwBytes) } + unsafe { HeapAlloc(heap, flags, bytes) } } #[inline(never)] fn process_heap_alloc( _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`, flags: u32, - dwBytes: usize, + bytes: usize, ) -> *mut c_void { let heap = HEAP.load(Ordering::Relaxed); if core::intrinsics::likely(!heap.is_null()) { // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, dwBytes) } + unsafe { HeapAlloc(heap, flags, bytes) } } else { - process_heap_init_and_alloc(MaybeUninit::uninit(), flags, dwBytes) + process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes) } } diff --git a/library/std/src/sys/pal/windows/alloc/tests.rs b/library/std/src/sys/alloc/windows/tests.rs index 674a3e1d92d..674a3e1d92d 100644 --- a/library/std/src/sys/pal/windows/alloc/tests.rs +++ b/library/std/src/sys/alloc/windows/tests.rs diff --git a/library/std/src/sys/pal/xous/alloc.rs b/library/std/src/sys/alloc/xous.rs index 9ea43445d02..9ea43445d02 100644 --- a/library/std/src/sys/pal/xous/alloc.rs +++ b/library/std/src/sys/alloc/xous.rs diff --git a/library/std/src/sys/pal/zkvm/alloc.rs b/library/std/src/sys/alloc/zkvm.rs index 2fdca223524..a600cfa2220 100644 --- a/library/std/src/sys/pal/zkvm/alloc.rs +++ b/library/std/src/sys/alloc/zkvm.rs @@ -1,5 +1,5 @@ -use super::abi; use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::sys::pal::abi; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index a86b3628f24..1ef17dd530f 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -5,6 +5,7 @@ /// descriptors. mod pal; +mod alloc; mod personality; pub mod anonymous_pipe; diff --git a/library/std/src/sys/pal/common/mod.rs b/library/std/src/sys/pal/common/mod.rs index 29fc0835d76..9af4dee401c 100644 --- a/library/std/src/sys/pal/common/mod.rs +++ b/library/std/src/sys/pal/common/mod.rs @@ -10,7 +10,6 @@ #![allow(dead_code)] -pub mod alloc; pub mod small_c_string; #[cfg(test)] diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index ef406b9ec7f..1f2e5d9469f 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -18,7 +18,6 @@ use crate::os::raw::c_char; -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 6321f92e3d9..4c0c0919f47 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -77,8 +77,11 @@ impl Thread { #[inline] pub fn sleep(dur: Duration) { + let micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 }; + let micros = u64::try_from(micros).unwrap_or(u64::MAX); + unsafe { - hermit_abi::usleep(dur.as_micros() as u64); + hermit_abi::usleep(micros); } } diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 851ab9b9f97..8d29b2ec619 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -9,7 +9,6 @@ use crate::io::ErrorKind; use crate::sync::atomic::{AtomicBool, Ordering}; pub mod abi; -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index 8179ec8821a..591be66fcb4 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -10,6 +10,7 @@ use crate::sync::Arc; use crate::sys::time::SystemTime; use crate::sys::unsupported; pub use crate::sys_common::fs::exists; +use crate::sys_common::ignore_notfound; /// A file descriptor. #[derive(Clone, Copy)] @@ -527,15 +528,23 @@ pub fn rmdir(p: &Path) -> io::Result<()> { pub fn remove_dir_all(path: &Path) -> io::Result<()> { for child in readdir(path)? { - let child = child?; - let child_type = child.file_type()?; - if child_type.is_dir() { - remove_dir_all(&child.path())?; - } else { - unlink(&child.path())?; + let result: io::Result<()> = try { + let child = child?; + let child_type = child.file_type()?; + if child_type.is_dir() { + remove_dir_all(&child.path())?; + } else { + unlink(&child.path())?; + } + }; + // ignore internal NotFound errors + if let Err(err) = result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } - rmdir(path) + ignore_notfound(rmdir(path)) } pub fn readlink(p: &Path) -> io::Result<PathBuf> { diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index cbf34286878..6ebcf5b7c48 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -16,7 +16,6 @@ pub mod itron { use super::unsupported; } -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; pub mod env; diff --git a/library/std/src/sys/pal/teeos/alloc.rs b/library/std/src/sys/pal/teeos/alloc.rs deleted file mode 100644 index b280d1dd76f..00000000000 --- a/library/std/src/sys/pal/teeos/alloc.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr; -use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN}; - -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // jemalloc provides alignment less than MIN_ALIGN for small allocations. - // So only rely on MIN_ALIGN if size >= align. - // Also see <https://github.com/rust-lang/rust/issues/45955> and - // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::malloc(layout.size()) as *mut u8 } - } else { - unsafe { aligned_malloc(&layout) } - } - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // See the comment above in `alloc` for why this check looks the way it does. - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::calloc(layout.size(), 1) as *mut u8 } - } else { - let ptr = unsafe { self.alloc(layout) }; - if !ptr.is_null() { - unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; - } - ptr - } - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - unsafe { libc::free(ptr as *mut libc::c_void) } - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } - } else { - unsafe { realloc_fallback(self, ptr, layout, new_size) } - } - } -} - -#[inline] -unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - let mut out = ptr::null_mut(); - // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. - // Since these are all powers of 2, we can just use max. - let align = layout.align().max(crate::mem::size_of::<usize>()); - let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) }; - if ret != 0 { ptr::null_mut() } else { out as *mut u8 } -} diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index adefd1bb42c..00e38604240 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -8,7 +8,6 @@ pub use self::rand::hashmap_random_keys; -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; #[path = "../unsupported/env.rs"] diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 851bcea4c1e..ac22f4ded88 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -13,11 +13,11 @@ //! [`OsString`]: crate::ffi::OsString #![forbid(unsafe_op_in_unsafe_fn)] -pub mod alloc; pub mod args; pub mod env; #[path = "../unsupported/fs.rs"] pub mod fs; +pub mod helpers; #[path = "../unsupported/io.rs"] pub mod io; #[path = "../unsupported/net.rs"] @@ -30,8 +30,6 @@ pub mod stdio; pub mod thread; pub mod time; -mod helpers; - #[cfg(test)] mod tests; diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index be13e1ae9b3..fc9d7e98883 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -2002,6 +2002,7 @@ mod remove_dir_impl { use crate::path::{Path, PathBuf}; use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::{cvt, cvt_r}; + use crate::sys_common::ignore_notfound; pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> { let fd = cvt_r(|| unsafe { @@ -2055,6 +2056,16 @@ mod remove_dir_impl { } } + fn is_enoent(result: &io::Result<()>) -> bool { + if let Err(err) = result + && matches!(err.raw_os_error(), Some(libc::ENOENT)) + { + true + } else { + false + } + } + fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> { // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &path) { @@ -2078,27 +2089,35 @@ mod remove_dir_impl { for child in dir { let child = child?; let child_name = child.name_cstr(); - match is_dir(&child) { - Some(true) => { - remove_dir_all_recursive(Some(fd), child_name)?; - } - Some(false) => { - cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; - } - None => { - // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed - // if the process has the appropriate privileges. This however can causing orphaned - // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing - // into it first instead of trying to unlink() it. - remove_dir_all_recursive(Some(fd), child_name)?; + // we need an inner try block, because if one of these + // directories has already been deleted, then we need to + // continue the loop, not return ok. + let result: io::Result<()> = try { + match is_dir(&child) { + Some(true) => { + remove_dir_all_recursive(Some(fd), child_name)?; + } + Some(false) => { + cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; + } + None => { + // POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed + // if the process has the appropriate privileges. This however can causing orphaned + // directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing + // into it first instead of trying to unlink() it. + remove_dir_all_recursive(Some(fd), child_name)?; + } } + }; + if result.is_err() && !is_enoent(&result) { + return result; } } // unlink the directory after removing its contents - cvt(unsafe { + ignore_notfound(cvt(unsafe { unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR) - })?; + }))?; Ok(()) } diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 10df3306f92..ba2f58f9c10 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -7,7 +7,6 @@ use crate::io::ErrorKind; #[macro_use] pub mod weak; -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 0fa610eebb4..c9dcc5ad97a 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -267,14 +267,32 @@ impl Thread { #[cfg(target_os = "espidf")] pub fn sleep(dur: Duration) { - let mut micros = dur.as_micros(); - unsafe { - while micros > 0 { - let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 }; + // ESP-IDF does not have `nanosleep`, so we use `usleep` instead. + // As per the documentation of `usleep`, it is expected to support + // sleep times as big as at least up to 1 second. + // + // ESP-IDF does support almost up to `u32::MAX`, but due to a potential integer overflow in its + // `usleep` implementation + // (https://github.com/espressif/esp-idf/blob/d7ca8b94c852052e3bc33292287ef4dd62c9eeb1/components/newlib/time.c#L210), + // we limit the sleep time to the maximum one that would not cause the underlying `usleep` implementation to overflow + // (`portTICK_PERIOD_MS` can be anything between 1 to 1000, and is 10 by default). + const MAX_MICROS: u32 = u32::MAX - 1_000_000 - 1; + + // Add any nanoseconds smaller than a microsecond as an extra microsecond + // so as to comply with the `std::thread::sleep` contract which mandates + // implementations to sleep for _at least_ the provided `dur`. + // We can't overflow `micros` as it is a `u128`, while `Duration` is a pair of + // (`u64` secs, `u32` nanos), where the nanos are strictly smaller than 1 second + // (i.e. < 1_000_000_000) + let mut micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 }; + + while micros > 0 { + let st = if micros > MAX_MICROS as u128 { MAX_MICROS } else { micros as u32 }; + unsafe { libc::usleep(st); - - micros -= st as u128; } + + micros -= st as u128; } } diff --git a/library/std/src/sys/pal/unsupported/alloc.rs b/library/std/src/sys/pal/unsupported/alloc.rs deleted file mode 100644 index d715ae45401..00000000000 --- a/library/std/src/sys/pal/unsupported/alloc.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr::null_mut; - -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - #[inline] - unsafe fn alloc_zeroed(&self, _layout: Layout) -> *mut u8 { - null_mut() - } - - #[inline] - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} - - #[inline] - unsafe fn realloc(&self, _ptr: *mut u8, _layout: Layout, _new_size: usize) -> *mut u8 { - null_mut() - } -} diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 442e6042ad5..01d516f7568 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,6 +1,5 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod alloc; pub mod args; pub mod env; pub mod fs; diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs index 6b6d1b8ff4e..52cfa202af8 100644 --- a/library/std/src/sys/pal/wasi/args.rs +++ b/library/std/src/sys/pal/wasi/args.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::ffi::{CStr, OsStr, OsString}; use crate::os::wasi::ffi::OsStrExt; diff --git a/library/std/src/sys/pal/wasi/env.rs b/library/std/src/sys/pal/wasi/env.rs index 730e356d7fe..8d444982673 100644 --- a/library/std/src/sys/pal/wasi/env.rs +++ b/library/std/src/sys/pal/wasi/env.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + pub mod os { pub const FAMILY: &str = ""; pub const OS: &str = ""; diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/pal/wasi/fd.rs index 8966e4b80ad..19b60157e2e 100644 --- a/library/std/src/sys/pal/wasi/fd.rs +++ b/library/std/src/sys/pal/wasi/fd.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] #![allow(dead_code)] use super::err2io; diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 11900886f0b..88b1e543ec7 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::fd::WasiFd; use crate::ffi::{CStr, OsStr, OsString}; @@ -13,7 +13,7 @@ use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::time::SystemTime; use crate::sys::unsupported; pub use crate::sys_common::fs::exists; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner}; use crate::{fmt, iter, ptr}; pub struct File { @@ -794,14 +794,22 @@ fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> { io::const_io_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found") })?; - if entry.file_type()?.is_dir() { - remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; - } else { - entry.inner.dir.fd.unlink_file(path)?; + let result: io::Result<()> = try { + if entry.file_type()?.is_dir() { + remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; + } else { + entry.inner.dir.fd.unlink_file(path)?; + } + }; + // ignore internal NotFound errors + if let Err(err) = &result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } // Once all this directory's contents are deleted it should be safe to // delete the directory tiself. - parent.remove_directory(osstr2str(path.as_ref())?) + ignore_notfound(parent.remove_directory(osstr2str(path.as_ref())?)) } diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs index 4b770ee23bc..d047bf2fce8 100644 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + use crate::{io as std_io, mem}; #[inline] diff --git a/library/std/src/sys/pal/wasi/io.rs b/library/std/src/sys/pal/wasi/io.rs index 2cd45df88fa..b7c2f03daa0 100644 --- a/library/std/src/sys/pal/wasi/io.rs +++ b/library/std/src/sys/pal/wasi/io.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::marker::PhantomData; use crate::os::fd::{AsFd, AsRawFd}; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index f4dc3ebd414..8051021a588 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -14,8 +14,6 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -#[path = "../unix/alloc.rs"] -pub mod alloc; pub mod args; pub mod env; pub mod fd; diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/pal/wasi/net.rs index b4cf94c8781..a6486799828 100644 --- a/library/std/src/sys/pal/wasi/net.rs +++ b/library/std/src/sys/pal/wasi/net.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::err2io; use super::fd::WasiFd; diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index f5b17d9df94..f7701360f5a 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use core::slice::memchr; diff --git a/library/std/src/sys/pal/wasi/stdio.rs b/library/std/src/sys/pal/wasi/stdio.rs index 4cc0e4ed5a4..ca49f871e19 100644 --- a/library/std/src/sys/pal/wasi/stdio.rs +++ b/library/std/src/sys/pal/wasi/stdio.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index c37acd8dfee..31c9cbd4699 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + use crate::ffi::CStr; use crate::num::NonZero; use crate::sys::unsupported; @@ -73,13 +75,13 @@ impl Thread { if #[cfg(target_feature = "atomics")] { pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> { let p = Box::into_raw(Box::new(p)); - let mut native: libc::pthread_t = mem::zeroed(); - let mut attr: libc::pthread_attr_t = mem::zeroed(); - assert_eq!(libc::pthread_attr_init(&mut attr), 0); + let mut native: libc::pthread_t = unsafe { mem::zeroed() }; + let mut attr: libc::pthread_attr_t = unsafe { mem::zeroed() }; + assert_eq!(unsafe { libc::pthread_attr_init(&mut attr) }, 0); let stack_size = cmp::max(stack, DEFAULT_MIN_STACK_SIZE); - match libc::pthread_attr_setstacksize(&mut attr, stack_size) { + match unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) } { 0 => {} n => { assert_eq!(n, libc::EINVAL); @@ -90,20 +92,20 @@ impl Thread { let page_size = os::page_size(); let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); - assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); + assert_eq!(unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) }, 0); } }; - let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + let ret = unsafe { libc::pthread_create(&mut native, &attr, thread_start, p as *mut _) }; // Note: if the thread creation fails and this assert fails, then p will // be leaked. However, an alternative design could cause double-free // which is clearly worse. - assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); + assert_eq!(unsafe {libc::pthread_attr_destroy(&mut attr) }, 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - drop(Box::from_raw(p)); + unsafe { drop(Box::from_raw(p)); } Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/library/std/src/sys/pal/wasi/time.rs b/library/std/src/sys/pal/wasi/time.rs index 016b06efbdc..0d8d0b59ac1 100644 --- a/library/std/src/sys/pal/wasi/time.rs +++ b/library/std/src/sys/pal/wasi/time.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::time::Duration; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index f20630e10cf..546fadbe501 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -6,8 +6,6 @@ //! To begin with, this target mirrors the wasi target 1 to 1, but over //! time this will change significantly. -#[path = "../unix/alloc.rs"] -pub mod alloc; #[path = "../wasi/args.rs"] pub mod args; #[path = "../wasi/env.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 4c34859e918..8141bfac49a 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -16,7 +16,6 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; pub mod env; diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index d99d4931de4..2134152ea93 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -14,7 +14,7 @@ use crate::sys::handle::Handle; use crate::sys::path::maybe_verbatim; use crate::sys::time::SystemTime; use crate::sys::{c, cvt, Align8}; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner}; use crate::{fmt, ptr, slice, thread}; pub struct File { @@ -1160,7 +1160,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); } - match remove_dir_all_iterative(&file, File::posix_delete) { + match ignore_notfound(remove_dir_all_iterative(&file, File::posix_delete)) { Err(e) => { if let Some(code) = e.raw_os_error() { match code as u32 { diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 6ed77fbc3d4..272fadd9150 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -15,7 +15,6 @@ pub mod compat; mod api; -pub mod alloc; pub mod args; pub mod c; pub mod env; diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 961d45c5e83..b211e94db65 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,6 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -pub mod alloc; #[path = "../unsupported/args.rs"] pub mod args; #[path = "../unsupported/env.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 651f25d6623..20fdb7468a4 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -10,7 +10,7 @@ const WORD_SIZE: usize = core::mem::size_of::<u32>(); -pub mod alloc; +pub mod abi; #[path = "../zkvm/args.rs"] pub mod args; pub mod env; @@ -26,13 +26,10 @@ pub mod pipe; #[path = "../unsupported/process.rs"] pub mod process; pub mod stdio; -#[path = "../unsupported/time.rs"] -pub mod time; - #[path = "../unsupported/thread.rs"] pub mod thread; - -mod abi; +#[path = "../unsupported/time.rs"] +pub mod time; use crate::io as std_io; diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index acb6713cf1b..a25a7244660 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -3,6 +3,7 @@ use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::path::Path; +use crate::sys_common::ignore_notfound; pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!( ErrorKind::InvalidInput, @@ -32,14 +33,22 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in fs::read_dir(path)? { - let child = child?; - if child.file_type()?.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else { - fs::remove_file(&child.path())?; + let result: io::Result<()> = try { + let child = child?; + if child.file_type()?.is_dir() { + remove_dir_all_recursive(&child.path())?; + } else { + fs::remove_file(&child.path())?; + } + }; + // ignore internal NotFound errors to prevent race conditions + if let Err(err) = &result + && err.kind() != io::ErrorKind::NotFound + { + return result; } } - fs::remove_dir(path) + ignore_notfound(fs::remove_dir(path)) } pub fn exists(path: &Path) -> io::Result<bool> { diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 60ee405ecaa..1c884f107be 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -80,3 +80,11 @@ pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 { // r < denom, so (denom*numer) is the upper bound of (r*numer) q * numer + r * numer / denom } + +pub fn ignore_notfound<T>(result: crate::io::Result<T>) -> crate::io::Result<()> { + match result { + Err(err) if err.kind() == crate::io::ErrorKind::NotFound => Ok(()), + Ok(_) => Ok(()), + Err(err) => Err(err), + } +} diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 69486705656..dcd5cd7f6b9 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -5,6 +5,10 @@ feature(stdarch_arm_feature_detection) )] #![cfg_attr( + all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + feature(stdarch_aarch64_feature_detection) +)] +#![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) )] @@ -36,21 +40,34 @@ fn aarch64_linux() { println!("bf16: {}", is_aarch64_feature_detected!("bf16")); println!("bti: {}", is_aarch64_feature_detected!("bti")); println!("crc: {}", is_aarch64_feature_detected!("crc")); + println!("cssc: {}", is_aarch64_feature_detected!("cssc")); println!("dit: {}", is_aarch64_feature_detected!("dit")); println!("dotprod: {}", is_aarch64_feature_detected!("dotprod")); println!("dpb2: {}", is_aarch64_feature_detected!("dpb2")); println!("dpb: {}", is_aarch64_feature_detected!("dpb")); + println!("ecv: {}", is_aarch64_feature_detected!("ecv")); println!("f32mm: {}", is_aarch64_feature_detected!("f32mm")); println!("f64mm: {}", is_aarch64_feature_detected!("f64mm")); + println!("faminmax: {}", is_aarch64_feature_detected!("faminmax")); println!("fcma: {}", is_aarch64_feature_detected!("fcma")); println!("fhm: {}", is_aarch64_feature_detected!("fhm")); + println!("flagm2: {}", is_aarch64_feature_detected!("flagm2")); println!("flagm: {}", is_aarch64_feature_detected!("flagm")); println!("fp16: {}", is_aarch64_feature_detected!("fp16")); + println!("fp8: {}", is_aarch64_feature_detected!("fp8")); + println!("fp8dot2: {}", is_aarch64_feature_detected!("fp8dot2")); + println!("fp8dot4: {}", is_aarch64_feature_detected!("fp8dot4")); + println!("fp8fma: {}", is_aarch64_feature_detected!("fp8fma")); + println!("fpmr: {}", is_aarch64_feature_detected!("fpmr")); println!("frintts: {}", is_aarch64_feature_detected!("frintts")); + println!("hbc: {}", is_aarch64_feature_detected!("hbc")); println!("i8mm: {}", is_aarch64_feature_detected!("i8mm")); println!("jsconv: {}", is_aarch64_feature_detected!("jsconv")); + println!("lse128: {}", is_aarch64_feature_detected!("lse128")); println!("lse2: {}", is_aarch64_feature_detected!("lse2")); println!("lse: {}", is_aarch64_feature_detected!("lse")); + println!("lut: {}", is_aarch64_feature_detected!("lut")); + println!("mops: {}", is_aarch64_feature_detected!("mops")); println!("mte: {}", is_aarch64_feature_detected!("mte")); println!("neon: {}", is_aarch64_feature_detected!("neon")); println!("paca: {}", is_aarch64_feature_detected!("paca")); @@ -58,20 +75,37 @@ fn aarch64_linux() { println!("pmull: {}", is_aarch64_feature_detected!("pmull")); println!("rand: {}", is_aarch64_feature_detected!("rand")); println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2")); + println!("rcpc3: {}", is_aarch64_feature_detected!("rcpc3")); println!("rcpc: {}", is_aarch64_feature_detected!("rcpc")); println!("rdm: {}", is_aarch64_feature_detected!("rdm")); println!("sb: {}", is_aarch64_feature_detected!("sb")); println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); + println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); + println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); + println!("sme-f8f32: {}", is_aarch64_feature_detected!("sme-f8f32")); + println!("sme-fa64: {}", is_aarch64_feature_detected!("sme-fa64")); + println!("sme-i16i64: {}", is_aarch64_feature_detected!("sme-i16i64")); + println!("sme-lutv2: {}", is_aarch64_feature_detected!("sme-lutv2")); + println!("sme2: {}", is_aarch64_feature_detected!("sme2")); + println!("sme2p1: {}", is_aarch64_feature_detected!("sme2p1")); + println!("sme: {}", is_aarch64_feature_detected!("sme")); println!("ssbs: {}", is_aarch64_feature_detected!("ssbs")); + println!("ssve-fp8dot2: {}", is_aarch64_feature_detected!("ssve-fp8dot2")); + println!("ssve-fp8dot4: {}", is_aarch64_feature_detected!("ssve-fp8dot4")); + println!("ssve-fp8fma: {}", is_aarch64_feature_detected!("ssve-fp8fma")); + println!("sve-b16b16: {}", is_aarch64_feature_detected!("sve-b16b16")); println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes")); println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm")); println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3")); println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4")); println!("sve2: {}", is_aarch64_feature_detected!("sve2")); + println!("sve2p1: {}", is_aarch64_feature_detected!("sve2p1")); println!("sve: {}", is_aarch64_feature_detected!("sve")); println!("tme: {}", is_aarch64_feature_detected!("tme")); + println!("wfxt: {}", is_aarch64_feature_detected!("wfxt")); // tidy-alphabetical-end } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4e8e0fd2532..71f69e03a9f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -79,6 +79,11 @@ def get(base, url, path, checksums, verbose=False): eprint("removing", temp_path) os.unlink(temp_path) +def curl_version(): + m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"])) + if m is None: + return (0, 0) + return (int(m[1]), int(m[2])) def download(path, url, probably_big, verbose): for _ in range(4): @@ -107,11 +112,15 @@ def _download(path, url, probably_big, verbose, exception): # If curl is not present on Win32, we should not sys.exit # but raise `CalledProcessError` or `OSError` instead require(["curl", "--version"], exception=platform_is_win32()) - run(["curl", option, + extra_flags = [] + if curl_version() > (7, 70): + extra_flags = [ "--retry-all-errors" ] + run(["curl", option] + extra_flags + [ "-L", # Follow redirect. "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds "--connect-timeout", "30", # timeout if cannot connect within 30 seconds "-o", path, + "--continue-at", "-", "--retry", "3", "-SRf", url], verbose=verbose, exception=True, # Will raise RuntimeError on failure @@ -533,9 +542,13 @@ class RustBuild(object): bin_root = self.bin_root() key = self.stage0_compiler.date - if self.rustc().startswith(bin_root) and \ - (not os.path.exists(self.rustc()) or - self.program_out_of_date(self.rustc_stamp(), key)): + is_outdated = self.program_out_of_date(self.rustc_stamp(), key) + need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \ + or is_outdated) + need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \ + or is_outdated) + + if need_rustc or need_cargo: if os.path.exists(bin_root): # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's # running. Kill it. @@ -556,7 +569,6 @@ class RustBuild(object): run_powershell([script]) shutil.rmtree(bin_root) - key = self.stage0_compiler.date cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or os.path.join(self.build_dir, "cache")) @@ -568,11 +580,16 @@ class RustBuild(object): toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix) - tarballs_to_download = [ - ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)), - ("rustc-{}".format(toolchain_suffix), "rustc"), - ("cargo-{}".format(toolchain_suffix), "cargo"), - ] + tarballs_to_download = [] + + if need_rustc: + tarballs_to_download.append( + ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)) + ) + tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc")) + + if need_cargo: + tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo")) tarballs_download_info = [ DownloadInfo( diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index ba6b0c2dbda..a338b9c8080 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -59,8 +59,6 @@ fn main() { if stage == "0" { cmd.arg("--cfg=bootstrap"); } - cmd.arg("-Zunstable-options"); - cmd.arg("--check-cfg=cfg(bootstrap)"); maybe_dump(format!("stage{stage}-rustdoc"), &cmd); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4353cfadd8d..edf18e2ebf3 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -199,16 +199,6 @@ impl Step for Std { builder.require_submodule("library/stdarch", None); - // Profiler information requires LLVM's compiler-rt - if builder.config.profiler { - builder.require_submodule( - "src/llvm-project", - Some( - "The `build.profiler` config option requires `compiler-rt` sources from LLVM.", - ), - ); - } - let mut target_deps = builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -466,6 +456,29 @@ pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> { } } +/// Tries to find LLVM's `compiler-rt` source directory, for building `library/profiler_builtins`. +/// +/// Normally it lives in the `src/llvm-project` submodule, but if we will be using a +/// downloaded copy of CI LLVM, then we try to use the `compiler-rt` sources from +/// there instead, which lets us avoid checking out the LLVM submodule. +fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf { + // Try to use `compiler-rt` sources from downloaded CI LLVM, if possible. + if builder.config.llvm_from_ci { + // CI LLVM might not have been downloaded yet, so try to download it now. + builder.config.maybe_download_ci_llvm(); + let ci_llvm_compiler_rt = builder.config.ci_llvm_root().join("compiler-rt"); + if ci_llvm_compiler_rt.exists() { + return ci_llvm_compiler_rt; + } + } + + // Otherwise, fall back to requiring the LLVM submodule. + builder.require_submodule("src/llvm-project", { + Some("The `build.profiler` config option requires `compiler-rt` sources from LLVM.") + }); + builder.src.join("src/llvm-project/compiler-rt") +} + /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) { @@ -473,8 +486,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + // Paths needed by `library/profiler_builtins/build.rs`. if let Some(path) = builder.config.profiler_path(target) { cargo.env("LLVM_PROFILER_RT_LIB", path); + } else if builder.config.profiler_enabled(target) { + let compiler_rt = compiler_rt_for_profiler(builder); + // Currently this is separate from the env var used by `compiler_builtins` + // (below) so that adding support for CI LLVM here doesn't risk breaking + // the compiler builtins. But they could be unified if desired. + cargo.env("RUST_COMPILER_RT_FOR_PROFILER", compiler_rt); } // Determine if we're going to compile in optimized C intrinsics to @@ -507,8 +527,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car ); let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); assert!(compiler_builtins_root.exists()); - // Note that `libprofiler_builtins/build.rs` also computes this so if - // you're changing something here please also change that. + // The path to `compiler-rt` is also used by `profiler_builtins` (above), + // so if you're changing something here please also change that as appropriate. cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); " compiler-builtins-c" } else { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 8d20b956213..4957de2e1b7 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -269,34 +269,45 @@ fn make_win_dist( let target_libs = find_files(&target_libs, &lib_path); // Copy runtime dlls next to rustc.exe - let dist_bin_dir = rust_root.join("bin/"); - fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed"); - for src in rustc_dlls { - builder.copy_link_to_folder(&src, &dist_bin_dir); + let rust_bin_dir = rust_root.join("bin/"); + fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed"); + for src in &rustc_dlls { + builder.copy_link_to_folder(src, &rust_bin_dir); + } + + if builder.config.lld_enabled { + // rust-lld.exe also needs runtime dlls + let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin"); + fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed"); + for src in &rustc_dlls { + builder.copy_link_to_folder(src, &rust_target_bin_dir); + } } //Copy platform tools to platform-specific bin directory - let target_bin_dir = - plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained"); - fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); + let plat_target_bin_self_contained_dir = + plat_root.join("lib/rustlib").join(target).join("bin/self-contained"); + fs::create_dir_all(&plat_target_bin_self_contained_dir) + .expect("creating plat_target_bin_self_contained_dir failed"); for src in target_tools { - builder.copy_link_to_folder(&src, &target_bin_dir); + builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir); } // Warn windows-gnu users that the bundled GCC cannot compile C files builder.create( - &target_bin_dir.join("GCC-WARNING.txt"), + &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"), "gcc.exe contained in this folder cannot be used for compiling C files - it is only \ used as a linker. In order to be able to compile projects containing C code use \ the GCC provided by MinGW or Cygwin.", ); //Copy platform libs to platform-specific lib directory - let target_lib_dir = - plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained"); - fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); + let plat_target_lib_self_contained_dir = + plat_root.join("lib/rustlib").join(target).join("lib/self-contained"); + fs::create_dir_all(&plat_target_lib_self_contained_dir) + .expect("creating plat_target_lib_self_contained_dir failed"); for src in target_libs { - builder.copy_link_to_folder(&src, &target_lib_dir); + builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir); } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 301633559fe..ffb617c642b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -303,10 +303,11 @@ fn invoke_rustdoc( .arg(&out) .arg(&path) .arg("--markdown-css") - .arg("../rust.css"); + .arg("../rust.css") + .arg("-Zunstable-options"); if !builder.config.docs_minification { - cmd.arg("-Z").arg("unstable-options").arg("--disable-minification"); + cmd.arg("--disable-minification"); } cmd.run(builder); @@ -376,8 +377,6 @@ impl Step for Standalone { } let mut cmd = builder.rustdoc_cmd(compiler); - // Needed for --index-page flag - cmd.arg("-Z").arg("unstable-options"); cmd.arg("--html-after-content") .arg(&footer) @@ -386,6 +385,7 @@ impl Step for Standalone { .arg("--html-in-header") .arg(&favicon) .arg("--markdown-no-toc") + .arg("-Zunstable-options") .arg("--index-page") .arg(builder.src.join("src/doc/index.md")) .arg("--markdown-playground-url") @@ -478,9 +478,6 @@ impl Step for Releases { mem::drop(tmpfile); let mut cmd = builder.rustdoc_cmd(compiler); - // Needed for --index-page flag - cmd.arg("-Z").arg("unstable-options"); - cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") @@ -490,6 +487,7 @@ impl Step for Releases { .arg("--markdown-no-toc") .arg("--markdown-css") .arg("rust.css") + .arg("-Zunstable-options") .arg("--index-page") .arg(builder.src.join("src/doc/index.md")) .arg("--markdown-playground-url") @@ -636,6 +634,8 @@ impl Step for Std { if !builder.config.docs_minification { extra_args.push("--disable-minification"); } + // For `--index-page` and `--output-format=json`. + extra_args.push("-Zunstable-options"); doc_std(builder, self.format, stage, target, &out, &extra_args, &crates); @@ -715,8 +715,6 @@ fn doc_std( .arg("--target-dir") .arg(&*target_dir.to_string_lossy()) .arg("-Zskip-rustdoc-fingerprint") - .rustdocflag("-Z") - .rustdocflag("unstable-options") .rustdocflag("--resource-suffix") .rustdocflag(&builder.version); for arg in extra_args { @@ -822,7 +820,6 @@ impl Step for Rustc { // Since we always pass --document-private-items, there's no need to warn about linking to private items. cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); cargo.rustdocflag("--show-type-layout"); // FIXME: `--generate-link-to-definition` tries to resolve cfged out code @@ -830,7 +827,6 @@ impl Step for Rustc { // cargo.rustdocflag("--generate-link-to-definition"); compile::rustc_cargo(builder, &mut cargo, target, &compiler); - cargo.arg("-Zunstable-options"); cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -986,7 +982,6 @@ macro_rules! tool_doc { cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("-Zunstable-options"); // FIXME: `--generate-link-to-definition` tries to resolve cfged out code // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // cargo.rustdocflag("--generate-link-to-definition"); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index c5a1ab78801..e1eea31b3bb 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -110,7 +110,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L // Initialize the llvm submodule if not initialized already. // If submodules are disabled, this does nothing. - builder.update_submodule("src/llvm-project"); + builder.config.update_submodule("src/llvm-project"); let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index ff8ca2ad74a..3a1eb43b801 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1096,7 +1096,7 @@ tool_extended!((self, builder), CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true; Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"]; Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"]; - CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, add_bins_to_sysroot = ["cargo-miri"]; + CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, add_bins_to_sysroot = ["cargo-miri"]; Rls, "src/tools/rls", "rls", stable=true; Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index a848163b272..ff0d1f3a725 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1612,7 +1612,6 @@ impl<'a> Builder<'a> { rustflags.arg("-Csymbol-mangling-version=v0"); } else { rustflags.arg("-Csymbol-mangling-version=legacy"); - rustflags.arg("-Zunstable-options"); } // Enable compile-time checking of `cfg` names, values and Cargo `features`. @@ -1860,16 +1859,7 @@ impl<'a> Builder<'a> { }, ); - let split_debuginfo = self.config.split_debuginfo(target); - let split_debuginfo_is_stable = target.contains("linux") - || target.contains("apple") - || (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed) - || (target.is_windows() && split_debuginfo == SplitDebuginfo::Off); - - if !split_debuginfo_is_stable { - rustflags.arg("-Zunstable-options"); - } - match split_debuginfo { + match self.config.split_debuginfo(target) { SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"), SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"), SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"), @@ -2046,7 +2036,6 @@ impl<'a> Builder<'a> { } if mode == Mode::Rustc { - rustflags.arg("-Zunstable-options"); rustflags.arg("-Wrustc::internal"); // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all // of the individual lints are satisfied. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bdd9fd755aa..bdfee55d8d1 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -14,7 +14,7 @@ use std::sync::OnceLock; use std::{cmp, env, fs}; use build_helper::exit; -use build_helper::git::GitConfig; +use build_helper::git::{output_result, GitConfig}; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; @@ -1885,6 +1885,22 @@ impl Config { warn("link-shared"); } + // FIXME(#129153): instead of all the ad-hoc `download-ci-llvm` checks that follow, + // use the `builder-config` present in tarballs since #128822 to compare the local + // config to the ones used to build the LLVM artifacts on CI, and only notify users + // if they've chosen a different value. + + if libzstd.is_some() { + println!( + "WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \ + like almost all `llvm.*` options, will be ignored and set by the LLVM CI \ + artifacts builder config." + ); + println!( + "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." + ); + } + // None of the LLVM options, except assertions, are supported // when using downloaded LLVM. We could just ignore these but // that's potentially confusing, so force them to not be @@ -1894,7 +1910,6 @@ impl Config { check_ci_llvm!(optimize_toml); check_ci_llvm!(thin_lto); check_ci_llvm!(release_debuginfo); - check_ci_llvm!(libzstd); check_ci_llvm!(targets); check_ci_llvm!(experimental_targets); check_ci_llvm!(clang_cl); @@ -2509,6 +2524,123 @@ impl Config { } } + /// Given a path to the directory of a submodule, update it. + /// + /// `relative_path` should be relative to the root of the git repository, not an absolute path. + /// + /// This *does not* update the submodule if `config.toml` explicitly says + /// not to, or if we're not in a git repository (like a plain source + /// tarball). Typically [`crate::Build::require_submodule`] should be + /// used instead to provide a nice error to the user if the submodule is + /// missing. + pub(crate) fn update_submodule(&self, relative_path: &str) { + if !self.submodules() { + return; + } + + let absolute_path = self.src.join(relative_path); + + // NOTE: The check for the empty directory is here because when running x.py the first time, + // the submodule won't be checked out. Check it out now so we can build it. + if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() + && !helpers::dir_is_empty(&absolute_path) + { + return; + } + + // Submodule updating actually happens during in the dry run mode. We need to make sure that + // all the git commands below are actually executed, because some follow-up code + // in bootstrap might depend on the submodules being checked out. Furthermore, not all + // the command executions below work with an empty output (produced during dry run). + // Therefore, all commands below are marked with `run_always()`, so that they also run in + // dry run mode. + let submodule_git = || { + let mut cmd = helpers::git(Some(&absolute_path)); + cmd.run_always(); + cmd + }; + + // Determine commit checked out in submodule. + let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]).as_command_mut()); + let checked_out_hash = checked_out_hash.trim_end(); + // Determine commit that the submodule *should* have. + let recorded = output( + helpers::git(Some(&self.src)) + .run_always() + .args(["ls-tree", "HEAD"]) + .arg(relative_path) + .as_command_mut(), + ); + + let actual_hash = recorded + .split_whitespace() + .nth(2) + .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); + + if actual_hash == checked_out_hash { + // already checked out + return; + } + + println!("Updating submodule {relative_path}"); + self.check_run( + helpers::git(Some(&self.src)) + .run_always() + .args(["submodule", "-q", "sync"]) + .arg(relative_path), + ); + + // Try passing `--progress` to start, then run git again without if that fails. + let update = |progress: bool| { + // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository, + // even though that has no relation to the upstream for the submodule. + let current_branch = output_result( + helpers::git(Some(&self.src)) + .allow_failure() + .run_always() + .args(["symbolic-ref", "--short", "HEAD"]) + .as_command_mut(), + ) + .map(|b| b.trim().to_owned()); + + let mut git = helpers::git(Some(&self.src)).allow_failure(); + git.run_always(); + if let Ok(branch) = current_branch { + // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. + // This syntax isn't accepted by `branch.{branch}`. Strip it. + let branch = branch.strip_prefix("heads/").unwrap_or(&branch); + git.arg("-c").arg(format!("branch.{branch}.remote=origin")); + } + git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]); + if progress { + git.arg("--progress"); + } + git.arg(relative_path); + git + }; + if !self.check_run(&mut update(true)) { + self.check_run(&mut update(false)); + } + + // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). + // diff-index reports the modifications through the exit status + let has_local_modifications = !self.check_run(submodule_git().allow_failure().args([ + "diff-index", + "--quiet", + "HEAD", + ])); + if has_local_modifications { + self.check_run(submodule_git().args(["stash", "push"])); + } + + self.check_run(submodule_git().args(["reset", "-q", "--hard"])); + self.check_run(submodule_git().args(["clean", "-qdfx"])); + + if has_local_modifications { + self.check_run(submodule_git().args(["stash", "pop"])); + } + } + #[cfg(feature = "bootstrap-self-test")] pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {} @@ -2613,19 +2745,23 @@ impl Config { asserts: bool, ) -> bool { let if_unchanged = || { - // Git is needed to track modifications here, but tarball source is not available. - // If not modified here or built through tarball source, we maintain consistency - // with '"if available"'. - if !self.rust_info.is_from_tarball() - && self - .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) - .is_none() - { - // there are some untracked changes in the given paths. - false - } else { - llvm::is_ci_llvm_available(self, asserts) + if self.rust_info.is_from_tarball() { + // Git is needed for running "if-unchanged" logic. + println!( + "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`." + ); + return false; } + + self.update_submodule("src/llvm-project"); + + // Check for untracked changes in `src/llvm-project`. + let has_changes = self + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none(); + + // Return false if there are untracked changes, otherwise check if CI LLVM is available. + if has_changes { false } else { llvm::is_ci_llvm_available(self, asserts) } }; match download_ci_llvm { diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index dd0309733ae..1e3f8da5258 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -22,6 +22,24 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { config.try_run(cmd) } +fn extract_curl_version(out: &[u8]) -> semver::Version { + let out = String::from_utf8_lossy(out); + // The output should look like this: "curl <major>.<minor>.<patch> ..." + out.lines() + .next() + .and_then(|line| line.split(" ").nth(1)) + .and_then(|version| semver::Version::parse(version).ok()) + .unwrap_or(semver::Version::new(1, 0, 0)) +} + +fn curl_version() -> semver::Version { + let mut curl = Command::new("curl"); + curl.arg("-V"); + let Ok(out) = curl.output() else { return semver::Version::new(1, 0, 0) }; + let out = out.stdout; + extract_curl_version(&out) +} + /// Generic helpers that are useful anywhere in bootstrap. impl Config { pub fn is_verbose(&self) -> bool { @@ -56,7 +74,7 @@ impl Config { /// Returns false if do not execute at all, otherwise returns its /// `status.success()`. pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool { - if self.dry_run() { + if self.dry_run() && !cmd.run_always { return true; } self.verbose(|| println!("running: {cmd:?}")); @@ -220,6 +238,8 @@ impl Config { "30", // timeout if cannot connect within 30 seconds "-o", tempfile.to_str().unwrap(), + "--continue-at", + "-", "--retry", "3", "-SRf", @@ -230,6 +250,10 @@ impl Config { } else { curl.arg("--progress-bar"); } + // --retry-all-errors was added in 7.71.0, don't use it if curl is old. + if curl_version() >= semver::Version::new(7, 71, 0) { + curl.arg("--retry-all-errors"); + } curl.arg(url); if !self.check_run(&mut curl) { if self.build.contains("windows-msvc") { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 784519a20a2..268392c5fb1 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -473,117 +473,6 @@ impl Build { build } - /// Given a path to the directory of a submodule, update it. - /// - /// `relative_path` should be relative to the root of the git repository, not an absolute path. - /// - /// This *does not* update the submodule if `config.toml` explicitly says - /// not to, or if we're not in a git repository (like a plain source - /// tarball). Typically [`Build::require_submodule`] should be - /// used instead to provide a nice error to the user if the submodule is - /// missing. - fn update_submodule(&self, relative_path: &str) { - if !self.config.submodules() { - return; - } - - let absolute_path = self.config.src.join(relative_path); - - // NOTE: The check for the empty directory is here because when running x.py the first time, - // the submodule won't be checked out. Check it out now so we can build it. - if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() - && !dir_is_empty(&absolute_path) - { - return; - } - - // Submodule updating actually happens during in the dry run mode. We need to make sure that - // all the git commands below are actually executed, because some follow-up code - // in bootstrap might depend on the submodules being checked out. Furthermore, not all - // the command executions below work with an empty output (produced during dry run). - // Therefore, all commands below are marked with `run_always()`, so that they also run in - // dry run mode. - let submodule_git = || { - let mut cmd = helpers::git(Some(&absolute_path)); - cmd.run_always(); - cmd - }; - - // Determine commit checked out in submodule. - let checked_out_hash = - submodule_git().args(["rev-parse", "HEAD"]).run_capture_stdout(self).stdout(); - let checked_out_hash = checked_out_hash.trim_end(); - // Determine commit that the submodule *should* have. - let recorded = helpers::git(Some(&self.src)) - .run_always() - .args(["ls-tree", "HEAD"]) - .arg(relative_path) - .run_capture_stdout(self) - .stdout(); - let actual_hash = recorded - .split_whitespace() - .nth(2) - .unwrap_or_else(|| panic!("unexpected output `{}`", recorded)); - - if actual_hash == checked_out_hash { - // already checked out - return; - } - - println!("Updating submodule {relative_path}"); - helpers::git(Some(&self.src)) - .run_always() - .args(["submodule", "-q", "sync"]) - .arg(relative_path) - .run(self); - - // Try passing `--progress` to start, then run git again without if that fails. - let update = |progress: bool| { - // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository, - // even though that has no relation to the upstream for the submodule. - let current_branch = helpers::git(Some(&self.src)) - .allow_failure() - .run_always() - .args(["symbolic-ref", "--short", "HEAD"]) - .run_capture_stdout(self) - .stdout_if_ok() - .map(|s| s.trim().to_owned()); - - let mut git = helpers::git(Some(&self.src)).allow_failure(); - git.run_always(); - if let Some(branch) = current_branch { - // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. - // This syntax isn't accepted by `branch.{branch}`. Strip it. - let branch = branch.strip_prefix("heads/").unwrap_or(&branch); - git.arg("-c").arg(format!("branch.{branch}.remote=origin")); - } - git.args(["submodule", "update", "--init", "--recursive", "--depth=1"]); - if progress { - git.arg("--progress"); - } - git.arg(relative_path); - git - }; - if !update(true).run(self) { - update(false).run(self); - } - - // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). - // diff-index reports the modifications through the exit status - let has_local_modifications = - !submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]).run(self); - if has_local_modifications { - submodule_git().args(["stash", "push"]).run(self); - } - - submodule_git().args(["reset", "-q", "--hard"]).run(self); - submodule_git().args(["clean", "-qdfx"]).run(self); - - if has_local_modifications { - submodule_git().args(["stash", "pop"]).run(self); - } - } - /// Updates a submodule, and exits with a failure if submodule management /// is disabled and the submodule does not exist. /// @@ -598,7 +487,7 @@ impl Build { if cfg!(test) && !self.config.submodules() { return; } - self.update_submodule(submodule); + self.config.update_submodule(submodule); let absolute_path = self.config.src.join(submodule); if dir_is_empty(&absolute_path) { let maybe_enable = if !self.config.submodules() @@ -646,7 +535,7 @@ impl Build { let path = Path::new(submodule); // Don't update the submodule unless it's already been cloned. if GitInfo::new(false, path).is_managed_git_subrepository() { - self.update_submodule(submodule); + self.config.update_submodule(submodule); } } } @@ -659,7 +548,7 @@ impl Build { } if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() { - self.update_submodule(submodule); + self.config.update_submodule(submodule); } } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index c629f04c00e..51a25104e4c 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -230,4 +230,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "./x test --rustc-args was renamed to --compiletest-rustc-args as it only applies there. ./x miri --rustc-args was also removed.", }, + ChangeInfo { + change_id: 129295, + severity: ChangeSeverity::Info, + summary: "The `build.profiler` option now tries to use source code from `download-ci-llvm` if possible, instead of checking out the `src/llvm-project` submodule.", + }, ]; diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 61e9694f1e2..e857f38e68a 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -62,9 +62,9 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ -# rustc's LLVM needs zstd. -COPY scripts/zstd.sh /tmp/ -RUN ./zstd.sh +# Build zstd to enable `llvm.libzstd`. +COPY host-x86_64/dist-x86_64-linux/build-zstd.sh /tmp/ +RUN ./build-zstd.sh COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/scripts/zstd.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh index a3d37ccc311..a3d37ccc311 100755 --- a/src/ci/docker/scripts/zstd.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-zstd.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index 19683317126..83c2aa8cfb3 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -28,5 +28,6 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-sanitizers \ --enable-profiler \ - --enable-compiler-docs + --enable-compiler-docs \ + --set llvm.libzstd=true ENV SCRIPT python3 ../x.py --stage 2 test diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index d690aac27fa..389abb2fdd3 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=v6.11-rc1 +LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee # Build rustc, rustdoc and cargo ../x.py build --stage 1 library rustdoc @@ -28,7 +28,7 @@ rm -rf linux || true # Download Linux at a specific commit mkdir -p linux git -C linux init -git -C linux remote add origin https://github.com/torvalds/linux.git +git -C linux remote add origin https://github.com/Rust-for-Linux/linux.git git -C linux fetch --depth 1 origin ${LINUX_VERSION} git -C linux checkout FETCH_HEAD diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index cb0b2e63452..b3a74a7716b 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -49,6 +49,7 @@ - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) + - [\*-unknown-trusty](platform-support/trusty.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md) - [hexagon-unknown-linux-musl](platform-support/hexagon-unknown-linux-musl.md) @@ -81,6 +82,7 @@ - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) + - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 667758a1203..0d79e5f4114 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -192,7 +192,7 @@ target | std | notes [`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline [`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten -`wasm32-unknown-unknown` | ✓ | WebAssembly +[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads @@ -264,6 +264,7 @@ target | std | host | notes [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS +[`aarch64-unknown-trusty`](platform-support/trusty.md) | ? | | `aarch64-uwp-windows-msvc` | ✓ | | [`aarch64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | ARM64 VxWorks OS `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) @@ -283,6 +284,7 @@ target | std | host | notes [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD [`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float +[`armv7-unknown-trusty`](platform-support/trusty.md) | ? | | [`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ✓ | | Armv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat diff --git a/src/doc/rustc/src/platform-support/trusty.md b/src/doc/rustc/src/platform-support/trusty.md new file mode 100644 index 00000000000..dec3b96ff64 --- /dev/null +++ b/src/doc/rustc/src/platform-support/trusty.md @@ -0,0 +1,51 @@ +# `aarch64-unknown-trusty` and `armv7-unknown-trusty` + +**Tier: 3** + +[Trusty] is a secure Operating System that provides a Trusted Execution +Environment (TEE) for Android. + +## Target maintainers + +- Nicole LeGare (@randomPoison) +- Stephen Crane (@rinon) +- As a fallback trusty-dev-team@google.com can be contacted + +## Requirements + +These targets are cross-compiled. They have no special requirements for the host. + +Support for the standard library is work-in-progress. It is expected that +they will support alloc with the default allocator, and partially support std. + +Trusty uses the ELF file format. + +## Building the target + +The targets can be built by enabling them for a `rustc` build, for example: + +```toml +[build] +build-stage = 1 +target = ["aarch64-unknown-trusty", "armv7-unknown-trusty"] +``` + +## Building Rust programs + +There is currently no supported way to build a Trusty app with Cargo. You can +follow the [Trusty build instructions] to build the Trusty kernel along with any +Rust apps that are setup in the project. + +## Testing + +See the [Trusty build instructions] for information on how to build Rust code +within the main Trusty project. The main project also includes infrastructure +for testing Rust applications within a QEMU emulator. + +## Cross-compilation toolchains and C code + +See the [Trusty build instructions] for information on how C code is built +within Trusty. + +[Trusty]: https://source.android.com/docs/security/features/trusty +[Trusty build instructions]: https://source.android.com/docs/security/features/trusty/download-and-build diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md new file mode 100644 index 00000000000..12b7817c382 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -0,0 +1,197 @@ +# `wasm32-unknown-unknown` + +**Tier: 2** + +The `wasm32-unknown-unknown` target is a WebAssembly compilation target which +does not import any functions from the host for the standard library. This is +the "minimal" WebAssembly in the sense of making the fewest assumptions about +the host environment. This target is often used when compiling to the web or +JavaScript environments as there is no standard for what functions can be +imported on the web. This target can also be useful for creating minimal or +bare-bones WebAssembly binaries. + +The `wasm32-unknown-unknown` target has support for the Rust standard library +but many parts of the standard library do not work and return errors. For +example `println!` does nothing, `std::fs` always return errors, and +`std::thread::spawn` will panic. There is no means by which this can be +overridden. For a WebAssembly target that more fully supports the standard +library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or +[`wasm32-wasip2`](./wasm32-wasip2.md) targets. + +The `wasm32-unknown-unknown` target has full support for the `core` and `alloc` +crates. It additionally supports the `HashMap` type in the `std` crate, although +hash maps are not randomized like they are on other platforms. + +One existing user of this target (please feel free to edit and expand this list +too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen) +which facilitates Rust code interoperating with JavaScript code. Note, though, +that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web. + +## Target maintainers + +When this target was added to the compiler, platform-specific documentation here +was not maintained at that time. This means that the list below is not +exhaustive, and there are more interested parties in this target. That being +said, those interested in maintaining this target are: + +- Alex Crichton, https://github.com/alexcrichton + +## Requirements + +This target is cross-compiled. The target includes support for `std` itself, +but as mentioned above many pieces of functionality that require an operating +system do not work and will return errors. + +This target currently has no equivalent in C/C++. There is no C/C++ toolchain +for this target. While interop is theoretically possible it's recommended to +instead use one of: + +* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten + toolchain is typically chosen for running C/C++. +* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to + compile C/C++ on this target and can interop with Rust code. WASI works on + the web so far as there's no blocker, but an implementation of WASI APIs + must be either chosen or reimplemented. + +This target has no build requirements beyond what's in-tree in the Rust +repository. Linking binaries requires LLD to be enabled for the `wasm-ld` +driver. This target uses the `dlmalloc` crate as the default global allocator. + +## Building the target + +Building this target can be done by: + +* Configure the `wasm32-unknown-unknown` target to get built. +* Configure LLD to be built. +* Ensure the `WebAssembly` target backend is not disabled in LLVM. + +These are all controlled through `config.toml` options. It should be possible +to build this target on any platform. + +## Building Rust programs + +Rust programs can be compiled by adding this target via rustup: + +```sh +$ rustup target add wasm32-unknown-unknown +``` + +and then compiling with the target: + +```sh +$ rustc foo.rs --target wasm32-unknown-unknown +$ file foo.wasm +``` + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target is not tested in CI for the rust-lang/rust repository. Many tests +must be disabled to run on this target and failures are non-obvious because +`println!` doesn't work in the standard library. It's recommended to test the +`wasm32-wasip1` target instead for WebAssembly compatibility. + +## Conditionally compiling code + +It's recommended to conditionally compile code for this target with: + +```text +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +``` + +Note that there is no way to tell via `#[cfg]` whether code will be running on +the web or not. + +## Enabled WebAssembly features + +WebAssembly is an evolving standard which adds new features such as new +instructions over time. This target's default set of supported WebAssembly +features will additionally change over time. The `wasm32-unknown-unknown` target +inherits the default settings of LLVM which typically matches the default +settings of Emscripten as well. + +Changes to WebAssembly go through a [proposals process][proposals] but reaching +the final stage (stage 5) does not automatically mean that the feature will be +enabled in LLVM and Rust by default. At this time the general guidance is that +features must be present in most engines for a "good chunk of time" before +they're enabled in LLVM by default. There is currently no exact number of +months or engines that are required to enable features by default. + +[proposals]: https://github.com/WebAssembly/proposals + +As of the time of this writing the proposals that are enabled by default (the +`generic` CPU in LLVM terminology) are: + +* `multivalue` +* `mutable-globals` +* `reference-types` +* `sign-ext` + +If you're compiling WebAssembly code for an engine that does not support a +feature in LLVM's default feature set then the feature must be disabled at +compile time. Note, though, that enabled features may be used in the standard +library or precompiled libraries shipped via rustup. This means that not only +does your own code need to be compiled with the correct set of flags but the +Rust standard library additionally must be recompiled. + +Compiling all code for the initial release of WebAssembly looks like: + +```sh +$ export RUSTFLAGS=-Ctarget-cpu=mvp +$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown +``` + +Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported +features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is +then used to recompile the standard library in addition to your own code. This +will produce a binary that uses only the original WebAssembly features by +default and no proposals since its inception. + +To enable individual features it can be done with `-Ctarget-feature=+foo`. +Available features for Rust code itself are documented in the [reference] and +can also be found through: + +```sh +$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown +``` + +You'll need to consult your WebAssembly engine's documentation to learn more +about the supported WebAssembly features the engine has. + +[reference]: https://doc.rust-lang.org/reference/attributes/codegen.html#wasm32-or-wasm64 + +Note that it is still possible for Rust crates and libraries to enable +WebAssembly features on a per-function level. This means that the build +command above may not be sufficient to disable all WebAssembly features. If the +final binary still has SIMD instructions, for example, the function in question +will need to be found and the crate in question will likely contain something +like: + +```rust,ignore (not-always-compiled-to-wasm) +#[target_feature(enable = "simd128")] +fn foo() { + // ... +} +``` + +In this situation there is no compiler flag to disable emission of SIMD +instructions and the crate must instead be modified to not include this function +at compile time either by default or through a Cargo feature. For crate authors +it's recommended to avoid `#[target_feature(enable = "...")]` except where +necessary and instead use: + +```rust,ignore (not-always-compiled-to-wasm) +#[cfg(target_feature = "simd128")] +fn foo() { + // ... +} +``` + +That is to say instead of enabling target features it's recommended to +conditionally compile code instead. This is notably different to the way native +platforms such as x86\_64 work, and this is due to the fact that WebAssembly +binaries must only contain code the engine understands. Native binaries work so +long as the CPU doesn't execute unknown code dynamically at runtime. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index c3eda26ca8e..994c0f4bbb3 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -162,3 +162,17 @@ It's recommended to conditionally compile code for this target with: Prior to Rust 1.80 the `target_env = "p1"` key was not set. Currently the `target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]` necessary to detect this target may change as the target becomes more stable. + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation includes two +more features in addition to that which +[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) enables: + +* `bulk-memory` +* `atomics` + +For more information about features see the documentation for +[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md), but note that the +`mvp` CPU in LLVM does not support this target as it's required that +`bulk-memory`, `atomics`, and `mutable-globals` are all enabled. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index fb70bbdc2b4..0e4def6768d 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -132,3 +132,9 @@ It's recommended to conditionally compile code for this target with: Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior to Rust 1.80 the `target_env` condition was not set. + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md index 1e53fbc178e..bb2348b201e 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md @@ -61,3 +61,9 @@ It's recommended to conditionally compile code for this target with: ```text #[cfg(all(target_os = "wasi", target_env = "p2"))] ``` + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 8e1b1d80fb6..5ea8b6cd542 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -449,8 +449,8 @@ entries, format it across multiple lines as with a type alias. ## extern items When writing extern items (such as `extern "C" fn`), always specify the ABI. -For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or -`extern "C" { ... }`. +For example, write `extern "C" fn foo ...` or `unsafe extern "C" { ...}` +and avoid `extern fn foo ...` and `unsafe extern { ... }`. ## Imports (`use` statements) diff --git a/src/doc/unstable-book/src/compiler-flags/embed-source.md b/src/doc/unstable-book/src/compiler-flags/embed-source.md new file mode 100644 index 00000000000..01a11e37797 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/embed-source.md @@ -0,0 +1,12 @@ +# `embed-source` + +This flag controls whether the compiler embeds the program source code text into +the object debug information section. It takes one of the following values: + +* `y`, `yes`, `on` or `true`: put source code in debug info. +* `n`, `no`, `off`, `false` or no value: omit source code from debug info (the default). + +This flag is ignored in configurations that don't emit DWARF debug information +and is ignored on non-LLVM backends. `-Z embed-source` requires DWARFv5. Use +`-Z dwarf-version=5` to control the compiler's DWARF target version and `-g` to +enable debug info generation. diff --git a/src/doc/unstable-book/src/language-features/struct-target-features.md b/src/doc/unstable-book/src/language-features/struct-target-features.md new file mode 100644 index 00000000000..e814fe90072 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/struct-target-features.md @@ -0,0 +1,7 @@ +# `struct_target_features` + +The tracking issue for this feature is: [#129107] + +[#129107]: https://github.com/rust-lang/rust/issues/129107 + +------------------------ diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b3fccbf6456..34332de80b3 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,7 +12,7 @@ rinja = { version = "0.3", default-features = false, features = ["config"] } base64 = "0.21.7" itertools = "0.12" indexmap = "2" -minifier = "0.3.0" +minifier = "0.3.1" pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index db81b4c4282..5260e363dd6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -272,7 +272,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> | rbv::ResolvedArg::LateBound(_, _, did) | rbv::ResolvedArg::Free(_, did), ) = cx.tcx.named_bound_var(lifetime.hir_id) - && let Some(lt) = cx.args.get(&did).and_then(|arg| arg.as_lt()) + && let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt()) { return lt.clone(); } diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 3dcef15b552..9754e1e6f74 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -162,7 +162,8 @@ impl ItemType { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::Closure => Self::ForeignType, + | DefKind::Closure + | DefKind::SyntheticCoroutineBody => Self::ForeignType, } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6357cfee141..5cbf8c5e19f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1288,56 +1288,90 @@ impl clean::Impl { if self.is_negative_trait_impl() { write!(f, "!")?; } - ty.print(cx).fmt(f)?; + if self.kind.is_fake_variadic() + && let generics = ty.generics() + && let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..]) + { + let last = ty.last(); + if f.alternate() { + write!(f, "{}<", last)?; + self.print_type(inner_type, f, use_absolute, cx)?; + write!(f, ">")?; + } else { + write!(f, "{}<", anchor(ty.def_id(), last, cx).to_string())?; + self.print_type(inner_type, f, use_absolute, cx)?; + write!(f, ">")?; + } + } else { + ty.print(cx).fmt(f)?; + } write!(f, " for ")?; } - if let clean::Type::Tuple(types) = &self.for_ - && let [clean::Type::Generic(name)] = &types[..] - && (self.kind.is_fake_variadic() || self.kind.is_auto()) - { - // Hardcoded anchor library/core/src/primitive_docs.rs - // Link should match `# Trait implementations` - primitive_link_fragment( - f, - PrimitiveType::Tuple, - format_args!("({name}₁, {name}₂, …, {name}ₙ)"), - "#trait-implementations-1", - cx, - )?; - } else if let clean::BareFunction(bare_fn) = &self.for_ - && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = - &bare_fn.decl.inputs.values[..] - && (self.kind.is_fake_variadic() || self.kind.is_auto()) - { - // Hardcoded anchor library/core/src/primitive_docs.rs - // Link should match `# Trait implementations` - - print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; - bare_fn.safety.print_with_space().fmt(f)?; - print_abi_with_space(bare_fn.abi).fmt(f)?; - let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; - primitive_link_fragment( - f, - PrimitiveType::Tuple, - format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), - "#trait-implementations-1", - cx, - )?; - // Write output. - if !bare_fn.decl.output.is_unit() { - write!(f, " -> ")?; - fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; - } - } else if let Some(ty) = self.kind.as_blanket_ty() { + if let Some(ty) = self.kind.as_blanket_ty() { fmt_type(ty, f, use_absolute, cx)?; } else { - fmt_type(&self.for_, f, use_absolute, cx)?; + self.print_type(&self.for_, f, use_absolute, cx)?; } print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f) }) } + fn print_type<'a, 'tcx: 'a>( + &self, + type_: &clean::Type, + f: &mut fmt::Formatter<'_>, + use_absolute: bool, + cx: &'a Context<'tcx>, + ) -> Result<(), fmt::Error> { + if let clean::Type::Tuple(types) = type_ + && let [clean::Type::Generic(name)] = &types[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + // Hardcoded anchor library/core/src/primitive_docs.rs + // Link should match `# Trait implementations` + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("({name}₁, {name}₂, …, {name}ₙ)"), + "#trait-implementations-1", + cx, + )?; + } else if let clean::Type::Array(ty, len) = type_ + && let clean::Type::Generic(name) = &**ty + && &len[..] == "1" + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?; + } else if let clean::BareFunction(bare_fn) = &type_ + && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = + &bare_fn.decl.inputs.values[..] + && (self.kind.is_fake_variadic() || self.kind.is_auto()) + { + // Hardcoded anchor library/core/src/primitive_docs.rs + // Link should match `# Trait implementations` + + print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?; + bare_fn.safety.print_with_space().fmt(f)?; + print_abi_with_space(bare_fn.abi).fmt(f)?; + let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" }; + primitive_link_fragment( + f, + PrimitiveType::Tuple, + format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), + "#trait-implementations-1", + cx, + )?; + // Write output. + if !bare_fn.decl.output.is_unit() { + write!(f, " -> ")?; + fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?; + } + } else { + fmt_type(&type_, f, use_absolute, cx)?; + } + Ok(()) + } } impl clean::Arguments { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c1b2ee7d8ae..47f321a4c4a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1730,6 +1730,7 @@ fn render_impl( let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"); + render_rightside(w, cx, item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>"); @@ -1751,6 +1752,7 @@ fn render_impl( let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"); + render_rightside(w, cx, item, render_mode); if trait_.is_some() { // Anchors are only used on trait impls. write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>"); diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 8a12bdef69b..d7682bd1c19 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -579,12 +579,14 @@ pub(crate) fn build_index<'tcx>( let mut names = Vec::with_capacity(self.items.len()); let mut types = String::with_capacity(self.items.len()); let mut full_paths = Vec::with_capacity(self.items.len()); - let mut parents = Vec::with_capacity(self.items.len()); + let mut parents = String::with_capacity(self.items.len()); + let mut parents_backref_queue = VecDeque::new(); let mut functions = String::with_capacity(self.items.len()); let mut deprecated = Vec::with_capacity(self.items.len()); - let mut backref_queue = VecDeque::new(); + let mut type_backref_queue = VecDeque::new(); + let mut last_name = None; for (index, item) in self.items.iter().enumerate() { let n = item.ty as u8; let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); @@ -597,17 +599,39 @@ pub(crate) fn build_index<'tcx>( "`{}` is missing idx", item.name ); - // 0 is a sentinel, everything else is one-indexed - parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0)); + assert!( + parents_backref_queue.len() <= 16, + "the string encoding only supports 16 slots of lookback" + ); + let parent: i32 = item.parent_idx.map(|x| x + 1).unwrap_or(0).try_into().unwrap(); + if let Some(idx) = parents_backref_queue.iter().position(|p: &i32| *p == parent) { + parents.push( + char::try_from('0' as u32 + u32::try_from(idx).unwrap()) + .expect("last possible value is '?'"), + ); + } else if parent == 0 { + write_vlqhex_to_string(parent, &mut parents); + } else { + parents_backref_queue.push_front(parent); + write_vlqhex_to_string(parent, &mut parents); + if parents_backref_queue.len() > 16 { + parents_backref_queue.pop_back(); + } + } - names.push(item.name.as_str()); + if Some(item.name.as_str()) == last_name { + names.push(""); + } else { + names.push(item.name.as_str()); + last_name = Some(item.name.as_str()); + } if !item.path.is_empty() { full_paths.push((index, &item.path)); } match &item.search_type { - Some(ty) => ty.write_to_string(&mut functions, &mut backref_queue), + Some(ty) => ty.write_to_string(&mut functions, &mut type_backref_queue), None => functions.push('`'), } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index a18b7a252a4..60dc142b9ff 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -75,11 +75,11 @@ pub(crate) fn write_shared( let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand" - let external_crates = hack_get_external_crate_names(&cx.dst)?; + let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?; let info = CrateInfo { src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, - all_crates: AllCratesPart::get(crate_name_json.clone())?, + all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, @@ -291,10 +291,13 @@ impl AllCratesPart { SortedTemplate::from_before_after("window.ALL_CRATES = [", "];") } - fn get(crate_name_json: OrderedJson) -> Result<PartsAndLocations<Self>, Error> { + fn get( + crate_name_json: OrderedJson, + resource_suffix: &str, + ) -> Result<PartsAndLocations<Self>, Error> { // external hack_get_external_crate_names not needed here, because // there's no way that we write the search index but not crates.js - let path = PathBuf::from("crates.js"); + let path = suffix_path("crates.js", resource_suffix); Ok(PartsAndLocations::with(path, crate_name_json)) } } @@ -305,8 +308,11 @@ impl AllCratesPart { /// /// This is to match the current behavior of rustdoc, which allows you to get all crates /// on the index page, even if --enable-index-page is only passed to the last crate. -fn hack_get_external_crate_names(doc_root: &Path) -> Result<Vec<String>, Error> { - let path = doc_root.join("crates.js"); +fn hack_get_external_crate_names( + doc_root: &Path, + resource_suffix: &str, +) -> Result<Vec<String>, Error> { + let path = doc_root.join(suffix_path("crates.js", resource_suffix)); let Ok(content) = fs::read_to_string(&path) else { // they didn't emit invocation specific, so we just say there were no crates return Ok(Vec::default()); diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs index 4d1874b7df5..e282cd99e43 100644 --- a/src/librustdoc/html/render/write_shared/tests.rs +++ b/src/librustdoc/html/render/write_shared/tests.rs @@ -6,10 +6,10 @@ use crate::html::render::write_shared::*; fn hack_external_crate_names() { let path = tempfile::TempDir::new().unwrap(); let path = path.path(); - let crates = hack_get_external_crate_names(&path).unwrap(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); assert!(crates.is_empty()); fs::write(path.join("crates.js"), r#"window.ALL_CRATES = ["a","b","c"];"#).unwrap(); - let crates = hack_get_external_crate_names(&path).unwrap(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); assert_eq!(crates, ["a".to_string(), "b".to_string(), "c".to_string()]); } @@ -60,7 +60,7 @@ fn all_crates_template() { #[test] fn all_crates_parts() { - let parts = AllCratesPart::get(OrderedJson::serialize("crate").unwrap()).unwrap(); + let parts = AllCratesPart::get(OrderedJson::serialize("crate").unwrap(), "").unwrap(); assert_eq!(&parts.parts[0].0, Path::new("crates.js")); assert_eq!(&parts.parts[0].1.to_string(), r#""crate""#); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index eb5a5d935e2..28df8d3f011 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1547,10 +1547,23 @@ instead, we check that it's not a "finger" cursor. margin-left: 24px; } +@keyframes targetfadein { + from { + background-color: var(--main-background-color); + } + 10% { + background-color: var(--target-border-color); + } + to { + background-color: var(--target-background-color); + } +} + :target { padding-right: 3px; background-color: var(--target-background-color); border-right: 3px solid var(--target-border-color); + animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; } .code-header a.tooltip { diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 3eb27ea087c..be0ec425946 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1393,6 +1393,7 @@ function initSearch(rawSearchIndex) { */ async function sortResults(results, isType, preferredCrate) { const userQuery = parsedQuery.userQuery; + const casedUserQuery = parsedQuery.original; const result_list = []; for (const result of results.values()) { result.item = searchIndex[result.id]; @@ -1403,6 +1404,13 @@ function initSearch(rawSearchIndex) { result_list.sort((aaa, bbb) => { let a, b; + // sort by exact case-sensitive match + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } + // sort by exact match with regard to the last word (mismatch goes later) a = (aaa.word !== userQuery); b = (bbb.word !== userQuery); @@ -3546,7 +3554,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\ // Used to de-duplicate inlined and re-exported stuff const itemReexports = new Map(crateCorpus.r); // an array of (Number) the parent path index + 1 to `paths`, or 0 if none - const itemParentIdxs = crateCorpus.i; + const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); // an array of [(Number) item type, @@ -3593,6 +3601,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\ // faster analysis operations lastPath = ""; len = itemTypes.length; + let lastName = ""; + let lastWord = ""; for (let i = 0; i < len; ++i) { const bitIndex = i + 1; if (descIndex >= descShard.len && @@ -3608,10 +3618,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\ descIndex = 0; descShardList.push(descShard); } - let word = ""; - if (typeof itemNames[i] === "string") { - word = itemNames[i].toLowerCase(); - } + const name = itemNames[i] === "" ? lastName : itemNames[i]; + const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; const type = itemFunctionDecoder.next(); if (type !== null) { @@ -3633,15 +3641,16 @@ ${item.displayPath}<span class="${type}">${name}</span>\ } // This object should have exactly the same set of fields as the "crateRow" // object defined above. + const itemParentIdx = itemParentIdxDecoder.next(); const row = { crate, ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" - name: itemNames[i], + name, path, descShard, descIndex, exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path, - parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined, + parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined, type, id, word, @@ -3655,6 +3664,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\ if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) { descIndex += 1; } + lastName = name; + lastWord = word; } if (aliases) { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5b96529fed7..eae12b84839 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -53,7 +53,7 @@ fn filter_assoc_items_by_name_and_namespace<'a>( assoc_items_of: DefId, ident: Ident, ns: Namespace, -) -> impl Iterator<Item = &ty::AssocItem> + 'a { +) -> impl Iterator<Item = &'a ty::AssocItem> + 'a { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) @@ -1950,7 +1950,9 @@ fn resolution_failure( | TraitAlias | TyParam | Static { .. } => "associated item", - Impl { .. } | GlobalAsm => unreachable!("not a path"), + Impl { .. } | GlobalAsm | SyntheticCoroutineBody => { + unreachable!("not a path") + } } } else { "associated item" diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index faf42b3aab1..23e298571d5 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -2,7 +2,7 @@ use std::mem; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; @@ -145,8 +145,9 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { let old = mem::replace(&mut self.update_retained, false); let ret = self.set_is_in_hidden_item_and_fold(true, i); self.update_retained = old; - if ret.is_crate() { - // We don't strip the crate, even if it has `#[doc(hidden)]`. + if ret.item_id == clean::ItemId::DefId(CRATE_DEF_ID.into()) { + // We don't strip the current crate, even if it has `#[doc(hidden)]`. + debug!("strip_hidden: Not strippping local crate"); Some(ret) } else { Some(strip_item(ret)) diff --git a/src/llvm-project b/src/llvm-project -Subproject ccf4c38bdd73f1a37ec266c73bdaef80e39f8cf +Subproject 2b259b3c201f939f2ed8d2fb0a0e9b37dd2d132 diff --git a/src/tools/cargo b/src/tools/cargo -Subproject ba8b39413c74d08494f94a7542fe79aa636e166 +Subproject 8f40fc59fb0c8df91c97405785197f3c630304e diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml index ce07290d1e1..d9c635df5dc 100644 --- a/src/tools/clippy/.cargo/config.toml +++ b/src/tools/clippy/.cargo/config.toml @@ -1,10 +1,10 @@ [alias] +bless = "test --config env.RUSTC_BLESS='1'" uitest = "test --test compile-test" -uibless = "test --test compile-test -- -- --bless" -bless = "test -- -- --bless" +uibless = "bless --test compile-test" dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " -collect-metadata = "test --test dogfood --features internal -- collect_metadata" +collect-metadata = "test --test compile-test --config env.COLLECT_METADATA='1'" [build] # -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh index 5a59f94ec91..d937661c0f8 100644 --- a/src/tools/clippy/.github/deploy.sh +++ b/src/tools/clippy/.github/deploy.sh @@ -10,6 +10,7 @@ mkdir out/master/ cp util/gh-pages/index.html out/master cp util/gh-pages/script.js out/master cp util/gh-pages/lints.json out/master +cp util/gh-pages/style.css out/master if [[ -n $TAG_NAME ]]; then echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it" diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml index 10e18e84c89..2aa13313fa5 100644 --- a/src/tools/clippy/.github/workflows/clippy_bors.yml +++ b/src/tools/clippy/.github/workflows/clippy_bors.yml @@ -136,11 +136,6 @@ jobs: - name: Test metadata collection run: cargo collect-metadata - - name: Test lint_configuration.md is up-to-date - run: | - echo "run \`cargo collect-metadata\` if this fails" - git update-index --refresh - integration_build: needs: changelog runs-on: ubuntu-latest diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index fddc2fd994e..9bc4ad9698d 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -5914,6 +5914,7 @@ Released 2018-09-13 [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args [`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo +[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 78409c7a09e..b48b881097f 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -30,8 +30,11 @@ color-print = "0.3.4" anstream = "0.6.0" [dev-dependencies] +cargo_metadata = "0.18.1" ui_test = "0.25" regex = "1.5.5" +serde = { version = "1.0.145", features = ["derive"] } +serde_json = "1.0.122" toml = "0.7.3" walkdir = "2.3" filetime = "0.2.9" @@ -41,7 +44,6 @@ itertools = "0.12" clippy_utils = { path = "clippy_utils" } if_chain = "1.0" quote = "1.0.25" -serde = { version = "1.0.145", features = ["derive"] } syn = { version = "2.0", features = ["full"] } futures = "0.3" parking_lot = "0.12" diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index a71d94daca7..963e02e5c16 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -739,7 +739,7 @@ for some users. Adding a configuration is done in the following steps: 5. Update [Lint Configuration](../lint_configuration.md) - Run `cargo collect-metadata` to generate documentation changes for the book. + Run `cargo bless --test config-metadata` to generate documentation changes for the book. [`clippy_config::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_config/src/conf.rs [`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index e3d550b1466..78348797588 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -1,5 +1,5 @@ <!-- -This file is generated by `cargo collect-metadata`. +This file is generated by `cargo bless --test config-metadata`. Please use that command to update the file and do not edit it by hand. --> @@ -199,7 +199,7 @@ Allowed names below the minimum allowed characters. The value `".."` can be used the list to indicate, that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` +**Default Value:** `["i", "j", "x", "y", "z", "w", "n"]` --- **Affected lints:** @@ -455,7 +455,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "AccessKit", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** @@ -949,5 +949,3 @@ Whether to also emit warnings for unsafe blocks with metavariable expansions in --- **Affected lints:** * [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe) - - diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index d5b28e25323..5c4e0761dbc 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] itertools = "0.12" -rustc-semver = "1.1" serde = { version = "1.0", features = ["derive"] } toml = "0.7.3" diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 4c2a8255d6b..a6f1b958bfb 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -1,7 +1,6 @@ use crate::msrvs::Msrv; use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename}; use crate::ClippyConfiguration; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; @@ -218,7 +217,7 @@ macro_rules! define_Conf { define_Conf! { /// Which crates to allow absolute paths from #[lints(absolute_paths)] - absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default(), + absolute_paths_allowed_crates: Vec<String> = Vec::new(), /// The maximum number of segments a path can have before being linted, anything above this will /// be linted. #[lints(absolute_paths)] @@ -280,12 +279,12 @@ define_Conf! { allowed_dotfiles: Vec<String> = Vec::default(), /// A list of crate names to allow duplicates of #[lints(multiple_crate_versions)] - allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default(), + allowed_duplicate_crates: Vec<String> = Vec::new(), /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of /// the list to indicate, that the configured values should be appended to the default /// configuration of Clippy. By default, any configuration will replace the default value. #[lints(min_ident_chars)] - allowed_idents_below_min_chars: FxHashSet<String> = + allowed_idents_below_min_chars: Vec<String> = DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(), /// List of prefixes to allow when determining whether an item's name ends with the module's name. /// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`), @@ -323,7 +322,7 @@ define_Conf! { /// 2. Paths with any segment that containing the word 'prelude' /// are already allowed by default. #[lints(wildcard_imports)] - allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default(), + allowed_wildcard_imports: Vec<String> = Vec::new(), /// Suppress checking of the passed type names in all types of operations. /// /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. @@ -355,7 +354,7 @@ define_Conf! { /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] /// ``` #[lints(arithmetic_side_effects)] - arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default(), + arithmetic_side_effects_allowed_binary: Vec<(String, String)> = <_>::default(), /// Suppress checking of the passed type names in unary operations like "negation" (`-`). /// /// #### Example @@ -431,7 +430,7 @@ define_Conf! { /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. #[lints(doc_markdown)] - doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(), + doc_valid_idents: Vec<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(), /// Whether to apply the raw pointer heuristic to determine if a type is `Send`. #[lints(non_send_fields_in_send_ty)] enable_raw_pointer_heuristic_for_send: bool = true, @@ -706,12 +705,12 @@ fn deserialize(file: &SourceFile) -> TryConf { DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS, ); // TODO: THIS SHOULD BE TESTED, this comment will be gone soon - if conf.conf.allowed_idents_below_min_chars.contains("..") { + if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") { conf.conf .allowed_idents_below_min_chars .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); } - if conf.conf.doc_valid_idents.contains("..") { + if conf.conf.doc_valid_idents.iter().any(|e| e == "..") { conf.conf .doc_valid_idents .extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string)); @@ -890,14 +889,14 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) { #[cfg(test)] mod tests { - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use serde::de::IgnoredAny; + use std::collections::{HashMap, HashSet}; use std::fs; use walkdir::WalkDir; #[test] fn configs_are_tested() { - let mut names: FxHashSet<String> = crate::get_configuration_metadata() + let mut names: HashSet<String> = crate::get_configuration_metadata() .into_iter() .map(|meta| meta.name.replace('_', "-")) .collect(); @@ -910,7 +909,7 @@ mod tests { for entry in toml_files { let file = fs::read_to_string(entry.path()).unwrap(); #[allow(clippy::zero_sized_map_values)] - if let Ok(map) = toml::from_str::<FxHashMap<String, IgnoredAny>>(&file) { + if let Ok(map) = toml::from_str::<HashMap<String, IgnoredAny>>(&file) { for name in map.keys() { names.remove(name.as_str()); } diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index d2246f12029..ac838cc81d2 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -14,7 +14,7 @@ )] extern crate rustc_ast; -extern crate rustc_data_structures; +extern crate rustc_attr; #[allow(unused_extern_crates)] extern crate rustc_driver; extern crate rustc_errors; diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index fc56ac51796..0e8215aa8e3 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -1,6 +1,6 @@ use rustc_ast::Attribute; -use rustc_semver::RustcVersion; -use rustc_session::Session; +use rustc_attr::parse_version; +use rustc_session::{RustcVersion, Session}; use rustc_span::{sym, Symbol}; use serde::Deserialize; use std::fmt; @@ -10,7 +10,7 @@ macro_rules! msrv_aliases { $($name:ident),* $(,)? })*) => { $($( - pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch); + pub const $name: RustcVersion = RustcVersion { major: $major, minor :$minor, patch: $patch }; )*)* }; } @@ -18,6 +18,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { 1,81,0 { LINT_REASONS_STABILIZATION } + 1,80,0 { BOX_INTO_ITER} 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } @@ -81,9 +82,9 @@ impl<'de> Deserialize<'de> for Msrv { D: serde::Deserializer<'de>, { let v = String::deserialize(deserializer)?; - RustcVersion::parse(&v) + parse_version(Symbol::intern(&v)) .map(|v| Msrv { stack: vec![v] }) - .map_err(|_| serde::de::Error::custom("not a valid Rust version")) + .ok_or_else(|| serde::de::Error::custom("not a valid Rust version")) } } @@ -95,7 +96,7 @@ impl Msrv { pub fn read_cargo(&mut self, sess: &Session) { let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION") .ok() - .and_then(|v| RustcVersion::parse(&v).ok()); + .and_then(|v| parse_version(Symbol::intern(&v))); match (self.current(), cargo_msrv) { (None, Some(cargo_msrv)) => self.stack = vec![cargo_msrv], @@ -115,7 +116,7 @@ impl Msrv { } pub fn meets(&self, required: RustcVersion) -> bool { - self.current().map_or(true, |version| version.meets(required)) + self.current().map_or(true, |msrv| msrv >= required) } fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> { @@ -131,7 +132,7 @@ impl Msrv { } if let Some(msrv) = msrv_attr.value_str() { - if let Ok(version) = RustcVersion::parse(msrv.as_str()) { + if let Some(version) = parse_version(msrv) { return Some(version); } diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index 755b04b0b23..fc15913354c 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -1,3 +1,4 @@ +#![feature(rustc_private)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index 15578d69c3a..8dbda1c634c 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -604,7 +604,7 @@ fn gen_declared_lints<'a>( details.sort_unstable(); let mut output = GENERATED_FILE_COMMENT.to_string(); - output.push_str("pub(crate) static LINTS: &[&crate::LintInfo] = &[\n"); + output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n"); for (is_public, module_name, lint_name) in details { if !is_public { diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 99ed93468a0..fbd4566da58 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -25,7 +25,6 @@ regex = { version = "1.5", optional = true } unicode-normalization = "0.1" unicode-script = { version = "0.5", default-features = false } semver = "1.0" -rustc-semver = "1.1" url = "2.2" [dev-dependencies] diff --git a/src/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index c0a9d888e0b..c72b3f1318c 100644 --- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::snippet_opt; +use clippy_utils::is_from_proc_macro; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; @@ -8,6 +8,7 @@ use rustc_hir::{HirId, ItemKind, Node, Path}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; +use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does @@ -24,6 +25,13 @@ declare_clippy_lint! { /// Note: One exception to this is code from macro expansion - this does not lint such cases, as /// using absolute paths is the proper way of referencing items in one. /// + /// ### Known issues + /// + /// There are currently a few cases which are not caught by this lint: + /// * Macro calls. e.g. `path::to::macro!()` + /// * Derive macros. e.g. `#[derive(path::to::macro)]` + /// * Attribute macros. e.g. `#[path::to::macro]` + /// /// ### Example /// ```no_run /// let x = std::f64::consts::PI; @@ -48,63 +56,66 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]); pub struct AbsolutePaths { pub absolute_paths_max_segments: u64, - pub absolute_paths_allowed_crates: &'static FxHashSet<String>, + pub absolute_paths_allowed_crates: FxHashSet<Symbol>, } impl AbsolutePaths { pub fn new(conf: &'static Conf) -> Self { Self { absolute_paths_max_segments: conf.absolute_paths_max_segments, - absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates, + absolute_paths_allowed_crates: conf + .absolute_paths_allowed_crates + .iter() + .map(|x| Symbol::intern(x)) + .collect(), } } } -impl LateLintPass<'_> for AbsolutePaths { +impl<'tcx> LateLintPass<'tcx> for AbsolutePaths { // We should only lint `QPath::Resolved`s, but since `Path` is only used in `Resolved` and `UsePath` // we don't need to use a visitor or anything as we can just check if the `Node` for `hir_id` isn't // a `Use` - #[expect(clippy::cast_possible_truncation)] - fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { - let Self { - absolute_paths_max_segments, - absolute_paths_allowed_crates, - } = self; - - if !path.span.from_expansion() - && let node = cx.tcx.hir_node(hir_id) - && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _))) - && let [first, rest @ ..] = path.segments - // Handle `::std` - && let (segment, len) = if first.ident.name == kw::PathRoot { - // Indexing is fine as `PathRoot` must be followed by another segment. `len() - 1` - // is fine here for the same reason - (&rest[0], path.segments.len() - 1) - } else { - (first, path.segments.len()) - } - && len > *absolute_paths_max_segments as usize - && let Some(segment_snippet) = snippet_opt(cx, segment.ident.span) - && segment_snippet == segment.ident.as_str() - { - let is_abs_external = - matches!(segment.res, Res::Def(DefKind::Mod, DefId { index, .. }) if index == CRATE_DEF_INDEX); - let is_abs_crate = segment.ident.name == kw::Crate; - - if is_abs_external && absolute_paths_allowed_crates.contains(segment.ident.name.as_str()) - || is_abs_crate && absolute_paths_allowed_crates.contains("crate") + fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, hir_id: HirId) { + let segments = match path.segments { + [] | [_] => return, + // Don't count enum variants and trait items as part of the length. + [rest @ .., _] + if let [.., s] = rest + && matches!(s.res, Res::Def(DefKind::Enum | DefKind::Trait | DefKind::TraitAlias, _)) => + { + rest + }, + path => path, + }; + if let [s1, s2, ..] = segments + && let has_root = s1.ident.name == kw::PathRoot + && let first = if has_root { s2 } else { s1 } + && let len = segments.len() - usize::from(has_root) + && len as u64 > self.absolute_paths_max_segments + && let crate_name = if let Res::Def(DefKind::Mod, DefId { index, .. }) = first.res + && index == CRATE_DEF_INDEX { + // `other_crate::foo` or `::other_crate::foo` + first.ident.name + } else if first.ident.name == kw::Crate || has_root { + // `::foo` or `crate::foo` + kw::Crate + } else { return; } - - if is_abs_external || is_abs_crate { - span_lint( - cx, - ABSOLUTE_PATHS, - path.span, - "consider bringing this path into scope with the `use` keyword", - ); - } + && !path.span.from_expansion() + && let node = cx.tcx.hir_node(hir_id) + && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(..))) + && !self.absolute_paths_allowed_crates.contains(&crate_name) + && !is_from_proc_macro(cx, path) + { + span_lint( + cx, + ABSOLUTE_PATHS, + path.span, + "consider bringing this path into scope with the `use` keyword", + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 3b4cc113480..56f5e903dc3 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -4,8 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; -use rustc_session::impl_lint_pass; +use rustc_session::{impl_lint_pass, RustcVersion}; use rustc_span::symbol; use std::f64::consts as f64; diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 6e336efbb90..55645d04eef 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap}; use clippy_utils::sugg::Sugg; -use clippy_utils::{is_diag_trait_item, last_path_segment, local_is_initialized, path_to_local}; +use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{self as hir, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -118,6 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { } ) && !clone_source_borrows_from_dest(cx, lhs, rhs.span) + && !is_in_test(cx.tcx, e.hir_id) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs index ca43e76ac57..7ff644b4c44 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs @@ -1,6 +1,6 @@ use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments}; +use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt}; use rustc_ast::{AttrKind, AttrStyle}; use rustc_lint::EarlyContext; use rustc_span::Span; @@ -26,7 +26,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { item.span.parent(), ); - if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) { + if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) { let lines = snippet.split('\n').collect::<Vec<_>>(); let lines = without_block_comments(lines); diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 8f430ae601a..3b14e9aee7f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -1,5 +1,3 @@ -//! checks for attributes - mod allow_attributes; mod allow_attributes_without_reason; mod blanket_clippy_restriction_lints; @@ -310,8 +308,8 @@ declare_clippy_lint! { /// ```rust,ignore /// #[allow(unused_mut)] /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() + /// let mut a = Vec::new(); + /// a.len() /// } /// ``` /// Use instead: diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs index 3fde7061585..877025cce4c 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs @@ -1,6 +1,6 @@ use super::{Attribute, NON_MINIMAL_CFG}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; @@ -29,8 +29,13 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { meta.span, "unneeded sub `cfg` when there is only one condition", |diag| { - if let Some(snippet) = snippet_opt(cx, list[0].span()) { - diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect); + if let Some(snippet) = list[0].span().get_source_text(cx) { + diag.span_suggestion( + meta.span, + "try", + snippet.to_owned(), + Applicability::MaybeIncorrect, + ); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs index 486e7c6ec4f..478ba7a187b 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs @@ -1,6 +1,7 @@ use super::{Attribute, UNNECESSARY_CLIPPY_CFG}; use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; +use itertools::Itertools; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, Level}; @@ -31,7 +32,7 @@ pub(super) fn check( return; } if nb_items == clippy_lints.len() { - if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) { + if let Some(snippet) = behind_cfg_attr.span.get_source_text(cx) { span_lint_and_sugg( cx, UNNECESSARY_CLIPPY_CFG, @@ -47,11 +48,7 @@ pub(super) fn check( ); } } else { - let snippet = clippy_lints - .iter() - .filter_map(|sp| snippet_opt(cx, *sp)) - .collect::<Vec<_>>() - .join(","); + let snippet = clippy_lints.iter().filter_map(|sp| sp.get_source_text(cx)).join(","); span_lint_and_note( cx, UNNECESSARY_CLIPPY_CFG, diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index f0868231d01..67ba605a59f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -1,7 +1,7 @@ use super::utils::{extract_clippy_lint, is_lint_level, is_word}; use super::{Attribute, USELESS_ATTRIBUTE}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{first_line_of_span, snippet_opt}; +use clippy_utils::source::{first_line_of_span, SpanRangeExt}; use rustc_ast::NestedMetaItem; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; @@ -69,14 +69,14 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) } let line_span = first_line_of_span(cx, attr.span); - if let Some(mut sugg) = snippet_opt(cx, line_span) { - if sugg.contains("#[") { + if let Some(src) = line_span.get_source_text(cx) { + if src.contains("#[") { + #[expect(clippy::collapsible_span_lint_calls)] span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| { - sugg = sugg.replacen("#[", "#![", 1); diag.span_suggestion( line_span, "if you just forgot a `!`, use", - sugg, + src.replacen("#[", "#![", 1), Applicability::MaybeIncorrect, ); }); diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index a2f48c18170..e933fdf1d6e 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -134,28 +134,30 @@ fn check_inverted_bool_in_condition( let suggestion = match (left.kind, right.kind) { (ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => { - let Some(left) = snippet_opt(cx, left_sub.span) else { + let Some(left) = left_sub.span.get_source_text(cx) else { return; }; - let Some(right) = snippet_opt(cx, right_sub.span) else { + let Some(right) = right_sub.span.get_source_text(cx) else { return; }; let Some(op) = bin_op_eq_str(op) else { return }; format!("{left} {op} {right}") }, (ExprKind::Unary(UnOp::Not, left_sub), _) => { - let Some(left) = snippet_opt(cx, left_sub.span) else { + let Some(left) = left_sub.span.get_source_text(cx) else { return; }; - let Some(right) = snippet_opt(cx, right.span) else { + let Some(right) = right.span.get_source_text(cx) else { return; }; let Some(op) = inverted_bin_op_eq_str(op) else { return }; format!("{left} {op} {right}") }, (_, ExprKind::Unary(UnOp::Not, right_sub)) => { - let Some(left) = snippet_opt(cx, left.span) else { return }; - let Some(right) = snippet_opt(cx, right_sub.span) else { + let Some(left) = left.span.get_source_text(cx) else { + return; + }; + let Some(right) = right_sub.span.get_source_text(cx) else { return; }; let Some(op) = inverted_bin_op_eq_str(op) else { return }; @@ -313,8 +315,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { self.output.push_str(&str); } else { self.output.push('!'); - let snip = snippet_opt(self.cx, terminal.span)?; - self.output.push_str(&snip); + self.output.push_str(&terminal.span.get_source_text(self.cx)?); } }, True | False | Not(_) => { @@ -345,8 +346,12 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } }, &Term(n) => { - let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?; - self.output.push_str(&snip); + self.output.push_str( + &self.terminals[n as usize] + .span + .source_callsite() + .get_source_text(self.cx)?, + ); }, } Some(()) @@ -370,8 +375,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { _ => None, } .and_then(|op| { - let lhs_snippet = snippet_opt(cx, lhs.span)?; - let rhs_snippet = snippet_opt(cx, rhs.span)?; + let lhs_snippet = lhs.span.get_source_text(cx)?; + let rhs_snippet = rhs.span.get_source_text(cx)?; if !(lhs_snippet.starts_with('(') && lhs_snippet.ends_with(')')) { if let (ExprKind::Cast(..), BinOpKind::Ge) = (&lhs.kind, binop.node) { @@ -399,7 +404,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { let path: &str = path.ident.name.as_str(); a == path }) - .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?))) + .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", receiver.span.get_source_text(cx)?))) }, _ => None, } diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index bd123a725a7..cba8224b84c 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -1,6 +1,6 @@ use crate::reference::DEREF_ADDROF; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; use rustc_errors::Applicability; @@ -73,6 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { } }) && !is_from_proc_macro(cx, e) + && let Some(deref_text) = deref_target.span.get_source_text(cx) { span_lint_and_then( cx, @@ -83,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { diag.span_suggestion( e.span, "if you would like to reborrow, try removing `&*`", - snippet_opt(cx, deref_target.span).unwrap(), + deref_text.as_str(), Applicability::MachineApplicable, ); @@ -98,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { diag.span_suggestion( e.span, "if you would like to deref, try using `&**`", - format!("&**{}", &snippet_opt(cx, deref_target.span).unwrap()), + format!("&**{deref_text}"), Applicability::MaybeIncorrect, ); }, diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs index 3af2d8c0256..fed0aa8b275 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs @@ -1,5 +1,3 @@ -//! lint on missing cargo common metadata - use cargo_metadata::Metadata; use clippy_utils::diagnostics::span_lint; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs index 312ad4c2990..96a2b161464 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs @@ -205,7 +205,7 @@ declare_clippy_lint! { } pub struct Cargo { - allowed_duplicate_crates: &'static FxHashSet<String>, + allowed_duplicate_crates: FxHashSet<String>, ignore_publish: bool, } @@ -221,7 +221,7 @@ impl_lint_pass!(Cargo => [ impl Cargo { pub fn new(conf: &'static Conf) -> Self { Self { - allowed_duplicate_crates: &conf.allowed_duplicate_crates, + allowed_duplicate_crates: conf.allowed_duplicate_crates.iter().cloned().collect(), ignore_publish: conf.cargo_ignore_publish, } } @@ -263,7 +263,7 @@ impl LateLintPass<'_> for Cargo { { match MetadataCommand::new().exec() { Ok(metadata) => { - multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates); + multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates); }, Err(e) => { for lint in WITH_DEPS_LINTS { diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs index 2769463c8a5..44cd1f7192f 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs @@ -1,5 +1,3 @@ -//! lint on multiple versions of a crate being used - use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId}; use clippy_utils::diagnostics::span_lint; use itertools::Itertools; diff --git a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs index f05fd3fcde5..15ecba20a0b 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).instantiate_identity() && let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next() && let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind() - && let Some(recv) = snippet_opt(cx, receiver.span) + && let Some(recv) = receiver.span.get_source_text(cx) { // `as_mut_ptr` might not exist let applicability = Applicability::MaybeIncorrect; diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index bd3acc06f4b..346aed7e9f1 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_const_context; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; @@ -34,7 +34,7 @@ pub(super) fn check( diag.help("an `as` cast can become silently lossy if the types change in the future"); let mut applicability = Applicability::MachineApplicable; let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "<from>", &mut applicability); - let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else { + let Some(ty) = hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt()).get_source_text(cx) else { return; }; match cast_to_hir.kind { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 102fe25fc67..5708aae3f3e 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -4,7 +4,7 @@ use clippy_utils::expr_or_init; use clippy_utils::source::snippet; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize}; -use rustc_errors::{Applicability, Diag, SuggestionStyle}; +use rustc_errors::{Applicability, Diag}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -190,12 +190,10 @@ fn offer_suggestion( format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, "..")) }; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "... or use `try_from` and handle the error accordingly", suggestion, Applicability::Unspecified, - // always show the suggestion in a separate line - SuggestionStyle::ShowAlways, ); } diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs index 5dc6df1e907..b22e8f4ee89 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; @@ -24,12 +24,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, expr.span, format!("casting function pointer `{from_snippet}` to `{cast_to}`"), |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "did you mean to invoke the function?", format!("{from_snippet}() as {cast_to}"), applicability, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index fb0b0cba6a6..566adc83d69 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{snippet_opt, SpanRangeExt}; use clippy_utils::visitors::{for_each_expr_without_closures, Visitable}; use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use rustc_ast::{LitFloatType, LitIntType, LitKind}; @@ -104,7 +104,7 @@ pub(super) fn check<'tcx>( let literal_str = &cast_str; if let LitKind::Int(n, _) = lit.node - && let Some(src) = snippet_opt(cx, cast_expr.span) + && let Some(src) = cast_expr.span.get_source_text(cx) && cast_to.is_floating_point() && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) && let from_nbits = 128 - n.get().leading_zeros() @@ -131,7 +131,7 @@ pub(super) fn check<'tcx>( | LitKind::Float(_, LitFloatType::Suffixed(_)) if cast_from.kind() == cast_to.kind() => { - if let Some(src) = snippet_opt(cx, cast_expr.span) { + if let Some(src) = cast_expr.span.get_source_text(cx) { if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) { lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to); return true; @@ -253,7 +253,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx let res = cx.qpath_res(&qpath, expr.hir_id); // Function call if let Res::Def(DefKind::Fn, def_id) = res { - let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else { + let Some(snippet) = cx.tcx.def_span(def_id).get_source_text(cx) else { return ControlFlow::Continue(()); }; // This is the worst part of this entire function. This is the only way I know of to diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs index 3c1c7d2dc3a..c5c4a28646d 100644 --- a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, Ty, TyKind}; @@ -20,7 +20,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_> let sugg = if let TyKind::Infer = mut_ty.ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) { + } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs index b54f392bf2f..d820c1e0720 100644 --- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs +++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs @@ -5,7 +5,7 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#{cfg(not(test))]`) + /// Checks for usage of `cfg` that excludes code from `test` builds. (i.e., `#[cfg(not(test))]`) /// /// ### Why is this bad? /// This may give the false impression that a codebase has 100% coverage, yet actually has untested code. diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 1711565fca8..dd7c34d1e46 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -1,5 +1,3 @@ -//! lint on manually implemented checked conversions that could be transformed into `try_from` - use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 5fa0522e4e5..0099eefbc8d 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -1,5 +1,3 @@ -//! calculate cognitive complexity and warn about overly complex functions - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{IntoSpan, SpanRangeExt}; diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs index f311c052ad6..e73bfc6ebf7 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs @@ -1,17 +1,3 @@ -//! Checks for if expressions that contain only an if expression. -//! -//! For example, the lint would catch: -//! -//! ```rust,ignore -//! if x { -//! if y { -//! println!("Hello world"); -//! } -//! } -//! ``` -//! -//! This lint is **warn** by default - use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability}; use clippy_utils::sugg::Sugg; diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index eebda3ff76f..c6847411c75 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use clippy_utils::visitors::{for_each_expr, Visitable}; use clippy_utils::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; @@ -7,7 +7,6 @@ use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; -use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does @@ -44,24 +43,11 @@ declare_clippy_lint! { } declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]); -// Add `String` here when it is added to diagnostic items -static COLLECTIONS: [Symbol; 9] = [ - sym::BTreeMap, - sym::BTreeSet, - sym::BinaryHeap, - sym::HashMap, - sym::HashSet, - sym::LinkedList, - sym::Option, - sym::Vec, - sym::VecDeque, -]; - impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { // Look for local variables whose type is a container. Search surrounding block for read access. if let PatKind::Binding(_, local_id, _, _) = local.pat.kind - && match_acceptable_type(cx, local, &COLLECTIONS) + && match_acceptable_type(cx, local) && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id) && has_no_read_access(cx, local_id, enclosing_block) { @@ -70,11 +56,22 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { } } -fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>, collections: &[Symbol]) -> bool { +fn match_acceptable_type(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool { let ty = cx.typeck_results().pat_ty(local.pat); - collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) - // String type is a lang item but not a diagnostic item for now so we need a separate check - || is_type_lang_item(cx, ty, LangItem::String) + matches!( + get_type_diagnostic_name(cx, ty), + Some( + sym::BTreeMap + | sym::BTreeSet + | sym::BinaryHeap + | sym::HashMap + | sym::HashSet + | sym::LinkedList + | sym::Option + | sym::Vec + | sym::VecDeque + ) + ) || is_type_lang_item(cx, ty, LangItem::String) } fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirId, block: T) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs index b49a977dbea..24570d8f440 100644 --- a/src/tools/clippy/clippy_lints/src/create_dir.rs +++ b/src/tools/clippy/clippy_lints/src/create_dir.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -46,7 +46,7 @@ impl LateLintPass<'_> for CreateDir { "calling `std::fs::create_dir` where there may be a better way", |diag| { let mut app = Applicability::MaybeIncorrect; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider calling `std::fs::create_dir_all` instead", format!( @@ -54,7 +54,6 @@ impl LateLintPass<'_> for CreateDir { snippet_with_applicability(cx, arg.span, "..", &mut app) ), app, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3fb083dd833..60e51713173 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -2,7 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. -pub(crate) static LINTS: &[&crate::LintInfo] = &[ +pub static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO, #[cfg(feature = "internal")] @@ -22,8 +22,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO, #[cfg(feature = "internal")] - crate::utils::internal_lints::metadata_collector::METADATA_COLLECTOR_INFO, - #[cfg(feature = "internal")] crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO, #[cfg(feature = "internal")] crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO, @@ -146,6 +144,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::doc::NEEDLESS_DOCTEST_MAIN_INFO, crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO, crate::doc::TEST_ATTR_IN_DOCTEST_INFO, + crate::doc::TOO_LONG_FIRST_DOC_PARAGRAPH_INFO, crate::doc::UNNECESSARY_SAFETY_DOC_INFO, crate::double_parens::DOUBLE_PARENS_INFO, crate::drop_forget_ref::DROP_NON_DROP_INFO, diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs index bd1cc46e185..771bcac2441 100644 --- a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs +++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use itertools::Itertools; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Span}; use std::ops::Range; @@ -59,12 +59,11 @@ pub(super) fn check( && (doc_comment == "///" || doc_comment == "//!") { // suggest filling in a blank line - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( line_break_span.shrink_to_lo(), "if this should be its own paragraph, add a blank doc comment line", format!("\n{doc_comment}"), Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); if ccount > 0 || blockquote_level > 0 { diag.help("if this not intended to be a quote at all, escape it with `\\>`"); @@ -79,12 +78,11 @@ pub(super) fn check( if ccount == 0 && blockquote_level == 0 { // simpler suggestion style for indentation let indent = list_indentation - lcount; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span.shrink_to_hi(), "indent this line", std::iter::repeat(" ").take(indent).join(""), Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); diag.help("if this is supposed to be its own paragraph, add a blank line"); return; @@ -107,12 +105,11 @@ pub(super) fn check( suggested.push_str(text); } } - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "add markers to start of line", suggested, Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); diag.help("if this not intended to be a quote at all, escape it with `\\>`"); }); diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs index 41c0bcd55ad..8cdaba88e50 100644 --- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs +++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_lint::LateContext; use rustc_span::{BytePos, Pos, Span}; use url::Url; @@ -92,6 +92,10 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b && matches!(prefix.chars().last(), Some('S' | 'X')) { prefix + } else if let Some(prefix) = s.strip_suffix("ified") + && prefix.chars().all(|c| c.is_ascii_uppercase()) + { + prefix } else { s.strip_suffix('s').unwrap_or(s) }; @@ -133,24 +137,15 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b } if has_underscore(word) || word.contains("::") || is_camel_case(word) || word.ends_with("()") { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_then( cx, DOC_MARKDOWN, span, "item in documentation is missing backticks", |diag| { + let mut applicability = Applicability::MachineApplicable; let snippet = snippet_with_applicability(cx, span, "..", &mut applicability); - diag.span_suggestion_with_style( - span, - "try", - format!("`{snippet}`"), - applicability, - // always show the suggestion in a separate line, since the - // inline presentation adds another pair of backticks - SuggestionStyle::ShowAlways, - ); + diag.span_suggestion_verbose(span, "try", format!("`{snippet}`"), applicability); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index d7b3a7c74f3..790579b21c9 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1,4 +1,6 @@ mod lazy_continuation; +mod too_long_first_doc_paragraph; + use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; @@ -309,7 +311,7 @@ declare_clippy_lint! { /// ### Known problems /// Inner doc comments can only appear before items, so there are certain cases where the suggestion /// made by this lint is not valid code. For example: - /// ```rs + /// ```rust /// fn foo() {} /// ///! /// fn bar() {} @@ -422,15 +424,47 @@ declare_clippy_lint! { "require every line of a paragraph to be indented and marked" } +declare_clippy_lint! { + /// ### What it does + /// Checks if the first line in the documentation of items listed in module page is too long. + /// + /// ### Why is this bad? + /// Documentation will show the first paragraph of the doscstring in the summary page of a + /// module, so having a nice, short summary in the first paragraph is part of writing good docs. + /// + /// ### Example + /// ```no_run + /// /// A very short summary. + /// /// A much longer explanation that goes into a lot more detail about + /// /// how the thing works, possibly with doclinks and so one, + /// /// and probably spanning a many rows. + /// struct Foo {} + /// ``` + /// Use instead: + /// ```no_run + /// /// A very short summary. + /// /// + /// /// A much longer explanation that goes into a lot more detail about + /// /// how the thing works, possibly with doclinks and so one, + /// /// and probably spanning a many rows. + /// struct Foo {} + /// ``` + #[clippy::version = "1.81.0"] + pub TOO_LONG_FIRST_DOC_PARAGRAPH, + style, + "ensure that the first line of a documentation paragraph isn't too long" +} + +#[derive(Clone)] pub struct Documentation { - valid_idents: &'static FxHashSet<String>, + valid_idents: FxHashSet<String>, check_private_items: bool, } impl Documentation { pub fn new(conf: &'static Conf) -> Self { Self { - valid_idents: &conf.doc_valid_idents, + valid_idents: conf.doc_valid_idents.iter().cloned().collect(), check_private_items: conf.check_private_items, } } @@ -448,48 +482,60 @@ impl_lint_pass!(Documentation => [ SUSPICIOUS_DOC_COMMENTS, EMPTY_DOCS, DOC_LAZY_CONTINUATION, + TOO_LONG_FIRST_DOC_PARAGRAPH, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) { - let Some(headers) = check_attrs(cx, self.valid_idents, attrs) else { + let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return; }; match cx.tcx.hir_node(cx.last_node_with_lint_attrs) { - Node::Item(item) => match item.kind { - ItemKind::Fn(sig, _, body_id) => { - if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { - let body = cx.tcx.hir().body(body_id); - - let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); - missing_headers::check( + Node::Item(item) => { + too_long_first_doc_paragraph::check( + cx, + item, + attrs, + headers.first_paragraph_len, + self.check_private_items, + ); + match item.kind { + ItemKind::Fn(sig, _, body_id) => { + if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) + || in_external_macro(cx.tcx.sess, item.span)) + { + let body = cx.tcx.hir().body(body_id); + + let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); + missing_headers::check( + cx, + item.owner_id, + sig, + headers, + Some(body_id), + panic_info, + self.check_private_items, + ); + } + }, + ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { + (false, Safety::Unsafe) => span_lint( cx, - item.owner_id, - sig, - headers, - Some(body_id), - panic_info, - self.check_private_items, - ); - } - }, - ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { - (false, Safety::Unsafe) => span_lint( - cx, - MISSING_SAFETY_DOC, - cx.tcx.def_span(item.owner_id), - "docs for unsafe trait missing `# Safety` section", - ), - (true, Safety::Safe) => span_lint( - cx, - UNNECESSARY_SAFETY_DOC, - cx.tcx.def_span(item.owner_id), - "docs for safe trait have unnecessary `# Safety` section", - ), + MISSING_SAFETY_DOC, + cx.tcx.def_span(item.owner_id), + "docs for unsafe trait missing `# Safety` section", + ), + (true, Safety::Safe) => span_lint( + cx, + UNNECESSARY_SAFETY_DOC, + cx.tcx.def_span(item.owner_id), + "docs for safe trait have unnecessary `# Safety` section", + ), + _ => (), + }, _ => (), - }, - _ => (), + } }, Node::TraitItem(trait_item) => { if let TraitItemKind::Fn(sig, ..) = trait_item.kind @@ -547,6 +593,7 @@ struct DocHeaders { safety: bool, errors: bool, panics: bool, + first_paragraph_len: usize, } /// Does some pre-processing on raw, desugared `#[doc]` attributes such as parsing them and @@ -653,6 +700,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize let mut paragraph_range = 0..0; let mut code_level = 0; let mut blockquote_level = 0; + let mut is_first_paragraph = true; let mut containers = Vec::new(); @@ -720,6 +768,10 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize } ticks_unbalanced = false; paragraph_range = range; + if is_first_paragraph { + headers.first_paragraph_len = doc[paragraph_range.clone()].chars().count(); + is_first_paragraph = false; + } }, End(TagEnd::Heading(_) | TagEnd::Paragraph | TagEnd::Item) => { if let End(TagEnd::Heading(_)) = event { diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs new file mode 100644 index 00000000000..7bb3bb12f2c --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -0,0 +1,91 @@ +use rustc_ast::ast::Attribute; +use rustc_errors::Applicability; +use rustc_hir::{Item, ItemKind}; +use rustc_lint::LateContext; + +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; +use clippy_utils::source::snippet_opt; + +use super::TOO_LONG_FIRST_DOC_PARAGRAPH; + +pub(super) fn check( + cx: &LateContext<'_>, + item: &Item<'_>, + attrs: &[Attribute], + mut first_paragraph_len: usize, + check_private_items: bool, +) { + if !check_private_items && !cx.effective_visibilities.is_exported(item.owner_id.def_id) { + return; + } + if first_paragraph_len <= 200 + || !matches!( + item.kind, + // This is the list of items which can be documented AND are displayed on the module + // page. So associated items or impl blocks are not part of this list. + ItemKind::Static(..) + | ItemKind::Const(..) + | ItemKind::Fn(..) + | ItemKind::Macro(..) + | ItemKind::Mod(..) + | ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::TraitAlias(..) + ) + { + return; + } + + let mut spans = Vec::new(); + let mut should_suggest_empty_doc = false; + + for attr in attrs { + if let Some(doc) = attr.doc_str() { + spans.push(attr.span); + let doc = doc.as_str(); + let doc = doc.trim(); + if spans.len() == 1 { + // We make this suggestion only if the first doc line ends with a punctuation + // because it might just need to add an empty line with `///`. + should_suggest_empty_doc = doc.ends_with('.') || doc.ends_with('!') || doc.ends_with('?'); + } + let len = doc.chars().count(); + if len >= first_paragraph_len { + break; + } + first_paragraph_len -= len; + } + } + + let &[first_span, .., last_span] = spans.as_slice() else { + return; + }; + if is_from_proc_macro(cx, item) { + return; + } + + span_lint_and_then( + cx, + TOO_LONG_FIRST_DOC_PARAGRAPH, + first_span.with_hi(last_span.lo()), + "first doc comment paragraph is too long", + |diag| { + if should_suggest_empty_doc + && let Some(second_span) = spans.get(1) + && let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi()) + && let Some(snippet) = snippet_opt(cx, new_span) + { + diag.span_suggestion( + new_span, + "add an empty line", + format!("{snippet}///\n"), + Applicability::MachineApplicable, + ); + } + }, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs index 02f9c2c3648..5315f55ba38 100644 --- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs +++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs @@ -1,5 +1,3 @@ -//! Lint on if expressions with an else if, but without a final else branch. - use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs index 1869faab1d3..f4c55738cb8 100644 --- a/src/tools/clippy/clippy_lints/src/empty_enum.rs +++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs @@ -1,5 +1,3 @@ -//! lint when there is an enum with no variants - use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index e54cd248ead..4755cefe784 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -1,6 +1,3 @@ -//! lint on C-like enums that are `repr(isize/usize)` and have values that -//! don't fit into an `i32` - use clippy_utils::consts::{mir_to_const, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{Item, ItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index a7e831fdc42..cabc6592258 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::higher::VecArgs; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::type_diagnostic_name; +use clippy_utils::ty::get_type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; @@ -139,7 +139,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc { let callee_ty_raw = typeck.expr_ty(callee); let callee_ty = callee_ty_raw.peel_refs(); - if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc)) + if matches!(get_type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc)) || !check_inputs(typeck, body.params, None, args) { return; diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index f095c1add91..012ad8e1a22 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::numeric_literal; use rustc_ast::ast::{self, LitFloatType, LitKind}; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, FloatTy}; @@ -117,12 +117,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { if type_suffix.is_none() { float_str.push_str(".0"); } - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider changing the type or replacing it with", numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); }, ); @@ -134,12 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { expr.span, "float has excessive precision", |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( expr.span, "consider changing the type or truncating it to", numeric_literal::format(&float_str, type_suffix, true), Applicability::MachineApplicable, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 0b248f784b7..4dedff69b9a 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::Sugg; use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; use rustc_errors::Applicability; @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), ([], [_]) => { // Simulate macro expansion, converting {{ and }} to { and }. - let Some(snippet) = snippet_opt(cx, format_args.span) else { + let Some(snippet) = format_args.span.get_source_text(cx) else { return; }; let s_expand = snippet.replace("{{", "{").replace("}}", "}"); @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { span_useless_format(cx, call_site, sugg, applicability); }, ([arg], [piece]) => { - if let Ok(value) = find_format_arg_expr(expr, arg) + if let Some(value) = find_format_arg_expr(expr, arg) && let FormatArgsPiece::Placeholder(placeholder) = piece && placeholder.format_trait == FormatTrait::Display && placeholder.format_options == FormatOptions::default() diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index a31d5cb6ec7..020c0c5440d 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -7,7 +7,7 @@ use clippy_utils::macros::{ find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall, }; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use itertools::Itertools; use rustc_ast::{ @@ -224,13 +224,11 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { if let FormatArgsPiece::Placeholder(placeholder) = piece && let Ok(index) = placeholder.argument.index && let Some(arg) = self.format_args.arguments.all_args().get(index) + && let Some(arg_expr) = find_format_arg_expr(self.expr, arg) { - let arg_expr = find_format_arg_expr(self.expr, arg); - self.check_unused_format_specifier(placeholder, arg_expr); - if let Ok(arg_expr) = arg_expr - && placeholder.format_trait == FormatTrait::Display + if placeholder.format_trait == FormatTrait::Display && placeholder.format_options == FormatOptions::default() && !self.is_aliased(index) { @@ -242,28 +240,13 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { } } - fn check_unused_format_specifier( - &self, - placeholder: &FormatPlaceholder, - arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>, - ) { - let ty_or_ast_expr = arg_expr.map(|expr| self.cx.typeck_results().expr_ty(expr).peel_refs()); - - let is_format_args = match ty_or_ast_expr { - Ok(ty) => is_type_lang_item(self.cx, ty, LangItem::FormatArguments), - Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)), - }; - + fn check_unused_format_specifier(&self, placeholder: &FormatPlaceholder, arg: &Expr<'_>) { let options = &placeholder.format_options; - let arg_span = match arg_expr { - Ok(expr) => expr.span, - Err(expr) => expr.span, - }; - if let Some(placeholder_span) = placeholder.span - && is_format_args && *options != FormatOptions::default() + && let ty = self.cx.typeck_results().expr_ty(arg).peel_refs() + && is_type_lang_item(self.cx, ty, LangItem::FormatArguments) { span_lint_and_then( self.cx, @@ -274,7 +257,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { let mut suggest_format = |spec| { let message = format!("for the {spec} to apply consider using `format!()`"); - if let Some(mac_call) = matching_root_macro_call(self.cx, arg_span, sym::format_args_macro) { + if let Some(mac_call) = matching_root_macro_call(self.cx, arg.span, sym::format_args_macro) { diag.span_suggestion( self.cx.sess().source_map().span_until_char(mac_call.span, '!'), message, @@ -424,7 +407,7 @@ impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()) && implements_trait(cx, target, display_trait_id, &[]) && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait() - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span.source_callsite()) + && let Some(receiver_snippet) = receiver.span.source_callsite().get_source_text(cx) { let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); if n_needed_derefs == 0 && !needs_ref { diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index e6f27cb82d1..7cd12ac7db8 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { && trait_name == self.format_trait_impl.name && let Ok(index) = placeholder.argument.index && let Some(arg) = format_args.arguments.all_args().get(index) - && let Ok(arg_expr) = find_format_arg_expr(self.expr, arg) + && let Some(arg_expr) = find_format_arg_expr(self.expr, arg) { self.check_format_arg_self(arg_expr); } diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 1c1d8b57bc4..b84bf7c821c 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::span_is_local; use clippy_utils::path_def_id; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, Visitor}; use rustc_hir::{ @@ -178,8 +178,8 @@ fn convert_to_from( return None; }; - let from = snippet_opt(cx, self_ty.span)?; - let into = snippet_opt(cx, target_ty.span)?; + let from = self_ty.span.get_source_text(cx)?; + let into = target_ty.span.get_source_text(cx)?; let mut suggestions = vec![ // impl Into<T> for U -> impl From<T> for U @@ -187,10 +187,10 @@ fn convert_to_from( (into_trait_seg.ident.span, String::from("From")), // impl Into<T> for U -> impl Into<U> for U // ~ ~ - (target_ty.span, from.clone()), + (target_ty.span, from.to_owned()), // impl Into<T> for U -> impl Into<T> for T // ~ ~ - (self_ty.span, into), + (self_ty.span, into.to_owned()), // fn into(self) -> T -> fn from(self) -> T // ~~~~ ~~~~ (impl_item.ident.span, String::from("from")), @@ -223,7 +223,7 @@ fn convert_to_from( } for span in finder.upper { - suggestions.push((span, from.clone())); + suggestions.push((span, from.to_owned())); } for span in finder.lower { suggestions.push((span, String::from("val"))); diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs index 6ab7bbc2dfc..e5fa67d6964 100644 --- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs +++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs @@ -22,8 +22,8 @@ declare_clippy_lint! { /// /// ### Known problems /// - /// This lint may suggest using (&<expression>).parse() instead of <expression>.parse() directly - /// in some cases, which is correct but adds unnecessary complexity to the code. + /// This lint may suggest using `(&<expression>).parse()` instead of `<expression>.parse()` + /// directly in some cases, which is correct but adds unnecessary complexity to the code. /// /// ### Example /// ```ignore diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs index cf85c74e688..05e341e06fd 100644 --- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_test; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, GenericParam, Generics, HirId, ImplItem, ImplItemKind, TraitItem, TraitItemKind}; @@ -18,20 +19,18 @@ fn report(cx: &LateContext<'_>, param: &GenericParam<'_>, generics: &Generics<'_ |diag| { if let Some(gen_span) = generics.span_for_param_suggestion() { // If there's already a generic param with the same bound, do not lint **this** suggestion. - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( gen_span, "add a type parameter", format!(", {{ /* Generic name */ }}: {}", ¶m.name.ident().as_str()[5..]), - rustc_errors::Applicability::HasPlaceholders, - rustc_errors::SuggestionStyle::ShowAlways, + Applicability::HasPlaceholders, ); } else { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( generics.span, "add a type parameter", format!("<{{ /* Generic name */ }}: {}>", ¶m.name.ident().as_str()[5..]), - rustc_errors::Applicability::HasPlaceholders, - rustc_errors::SuggestionStyle::ShowAlways, + Applicability::HasPlaceholders, ); } }, diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index b179d7b5249..93828121047 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -8,11 +8,11 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, Span}; use clippy_utils::attrs::is_proc_macro; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{return_ty, trait_ref_of_method}; @@ -129,9 +129,9 @@ fn check_needless_must_use( cx, DOUBLE_MUST_USE, fn_header_span, - "this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`", + "this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`", None, - "either add some descriptive text or remove the attribute", + "either add some descriptive message or remove the attribute", ); } } @@ -155,7 +155,7 @@ fn check_must_use_candidate<'tcx>( return; } span_lint_and_then(cx, MUST_USE_CANDIDATE, fn_span, msg, |diag| { - if let Some(snippet) = snippet_opt(cx, fn_span) { + if let Some(snippet) = fn_span.get_source_text(cx) { diag.span_suggestion( fn_span, "add the attribute", @@ -193,17 +193,13 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) } } -static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc]; - fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) -> bool { match *ty.kind() { // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, args) => { tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) - || KNOWN_WRAPPER_TYS - .iter() - .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did())) + || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys)) }, ty::Tuple(args) => args.iter().any(|ty| is_mutable_ty(cx, ty, tys)), diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs index 586ca58d60d..0f5ce340c44 100644 --- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs @@ -1,12 +1,11 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::SpanRangeExt; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::Span; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::source::snippet_opt; - use super::TOO_MANY_LINES; pub(super) fn check_fn( @@ -22,57 +21,57 @@ pub(super) fn check_fn( return; } - let Some(code_snippet) = snippet_opt(cx, body.value.span) else { - return; - }; let mut line_count: u64 = 0; - let mut in_comment = false; - let mut code_in_line; + let too_many = body.value.span.check_source_text(cx, |src| { + let mut in_comment = false; + let mut code_in_line; - let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..)) - && code_snippet.as_bytes().first().copied() == Some(b'{') - && code_snippet.as_bytes().last().copied() == Some(b'}') - { - // Removing the braces from the enclosing block - &code_snippet[1..code_snippet.len() - 1] - } else { - &code_snippet - } - .trim() // Remove leading and trailing blank lines - .lines(); + let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..)) + && src.as_bytes().first().copied() == Some(b'{') + && src.as_bytes().last().copied() == Some(b'}') + { + // Removing the braces from the enclosing block + &src[1..src.len() - 1] + } else { + src + } + .trim() // Remove leading and trailing blank lines + .lines(); - for mut line in function_lines { - code_in_line = false; - loop { - line = line.trim_start(); - if line.is_empty() { - break; - } - if in_comment { - if let Some(i) = line.find("*/") { - line = &line[i + 2..]; - in_comment = false; - continue; + for mut line in function_lines { + code_in_line = false; + loop { + line = line.trim_start(); + if line.is_empty() { + break; } - } else { - let multi_idx = line.find("/*").unwrap_or(line.len()); - let single_idx = line.find("//").unwrap_or(line.len()); - code_in_line |= multi_idx > 0 && single_idx > 0; - // Implies multi_idx is below line.len() - if multi_idx < single_idx { - line = &line[multi_idx + 2..]; - in_comment = true; - continue; + if in_comment { + if let Some(i) = line.find("*/") { + line = &line[i + 2..]; + in_comment = false; + continue; + } + } else { + let multi_idx = line.find("/*").unwrap_or(line.len()); + let single_idx = line.find("//").unwrap_or(line.len()); + code_in_line |= multi_idx > 0 && single_idx > 0; + // Implies multi_idx is below line.len() + if multi_idx < single_idx { + line = &line[multi_idx + 2..]; + in_comment = true; + continue; + } } + break; + } + if code_in_line { + line_count += 1; } - break; - } - if code_in_line { - line_count += 1; } - } + line_count > too_many_lines_threshold + }); - if line_count > too_many_lines_threshold { + if too_many { span_lint( cx, TOO_MANY_LINES, diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs index 0ebd8d0c237..120c5396a1c 100644 --- a/src/tools/clippy/clippy_lints/src/if_not_else.rs +++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs @@ -1,6 +1,3 @@ -//! lint on if branches that could be swapped so no `!` operation is necessary -//! on the condition - use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_else_clause; diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index b926e1e62ba..ba06567b957 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -3,7 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context, wal use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro}; use core::ops::ControlFlow; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -54,13 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) { |diag| { let mut app = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, span, "..", &mut app); - diag.span_suggestion_with_style( - span, - "add `return` as shown", - format!("return {snip}"), - app, - SuggestionStyle::ShowAlways, - ); + diag.span_suggestion_verbose(span, "add `return` as shown", format!("return {snip}"), app); }, ); } @@ -75,12 +69,11 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp |diag| { let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( break_span, "change `break` to `return` as shown", format!("return {snip}"), app, - SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index 0ef5b803a89..2ad045e1268 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -7,8 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; -use rustc_semver::RustcVersion; -use rustc_session::impl_lint_pass; +use rustc_session::{impl_lint_pass, RustcVersion}; use rustc_span::def_id::DefId; use rustc_span::{ExpnKind, Span}; @@ -65,18 +64,18 @@ impl IncompatibleMsrv { StabilityLevel::Stable { since: StableSince::Version(version), .. - } => Some(RustcVersion::new( - version.major.into(), - version.minor.into(), - version.patch.into(), - )), + } => Some(version), _ => None, }) { version } else if let Some(parent_def_id) = tcx.opt_parent(def_id) { self.get_def_id_version(tcx, parent_def_id) } else { - RustcVersion::new(1, 0, 0) + RustcVersion { + major: 1, + minor: 0, + patch: 0, + } }; self.is_above_msrv.insert(def_id, version); version diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs index 5b0aadf35c6..d386bfca6ba 100644 --- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::fulfill_or_allowed; use clippy_utils::source::snippet; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; @@ -71,6 +72,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { && let ty = cx.typeck_results().expr_ty(expr) && let Some(adt_def) = ty.ty_adt_def() && adt_def.is_struct() + && let Some(local_def_id) = adt_def.did().as_local() + && let ty_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id) && let Some(variant) = adt_def.variants().iter().next() { let mut def_order_map = FxHashMap::default(); @@ -103,15 +106,17 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor { snippet(cx, qpath.span(), ".."), ); - span_lint_and_sugg( - cx, - INCONSISTENT_STRUCT_CONSTRUCTOR, - expr.span, - "struct constructor field order is inconsistent with struct definition field order", - "try", - sugg, - Applicability::MachineApplicable, - ); + if !fulfill_or_allowed(cx, INCONSISTENT_STRUCT_CONSTRUCTOR, Some(ty_hir_id)) { + span_lint_and_sugg( + cx, + INCONSISTENT_STRUCT_CONSTRUCTOR, + expr.span, + "struct constructor field order is inconsistent with struct definition field order", + "try", + sugg, + Applicability::MachineApplicable, + ); + } } } } diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 3ac50b8f1fb..22e9674714f 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -1,5 +1,3 @@ -//! lint on indexing and slicing operations - use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 676d50c4951..71c317552ee 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::higher; -use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; use rustc_hir::{BorrowKind, Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; declare_clippy_lint! { /// ### What it does @@ -210,18 +210,6 @@ const COMPLETING_METHODS: [(&str, usize); 12] = [ ("product", 0), ]; -/// the paths of types that are known to be infinitely allocating -const INFINITE_COLLECTORS: &[Symbol] = &[ - sym::BinaryHeap, - sym::BTreeMap, - sym::BTreeSet, - sym::HashMap, - sym::HashSet, - sym::LinkedList, - sym::Vec, - sym::VecDeque, -]; - fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { match expr.kind { ExprKind::MethodCall(method, receiver, args, _) => { @@ -248,10 +236,19 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { } } else if method.ident.name == sym!(collect) { let ty = cx.typeck_results().expr_ty(expr); - if INFINITE_COLLECTORS - .iter() - .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item)) - { + if matches!( + get_type_diagnostic_name(cx, ty), + Some( + sym::BinaryHeap + | sym::BTreeMap + | sym::BTreeSet + | sym::HashMap + | sym::HashSet + | sym::LinkedList + | sym::Vec + | sym::VecDeque, + ) + ) { return is_infinite(cx, receiver); } } diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index 9eed7aa9243..d39f910f993 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -1,5 +1,3 @@ -//! lint on inherent implementations - use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use rustc_data_structures::fx::FxHashMap; diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 5657c58bb0a..1b900f6be8e 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -1,5 +1,3 @@ -//! checks for `#[inline]` on trait methods without bodies - use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::DiagExt; use rustc_errors::Applicability; diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs index b8e0eef7c7e..fc575bff7e6 100644 --- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs +++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,5 @@ -//! lint on blocks unnecessarily using >= with a + 1 or - 1 - use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; @@ -132,8 +130,8 @@ impl IntPlusOne { BinOpKind::Le => "<", _ => return None, }; - if let Some(snippet) = snippet_opt(cx, node.span) { - if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) { + if let Some(snippet) = node.span.get_source_text(cx) { + if let Some(other_side_snippet) = other_side.span.get_source_text(cx) { let rec = match side { Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 4d44bae02b8..74bf82f58bd 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -1,5 +1,3 @@ -//! lint on enum variants that are prefixed or suffixed by the same characters - use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::is_bool; diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index a88d8e24fda..4f066113aea 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -1,5 +1,3 @@ -//! lint when items are used after statements - use clippy_utils::diagnostics::span_lint_hir; use rustc_hir::{Block, ItemKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 3614fb8cc96..8caa484bb99 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::{HirId, Item, ItemKind, Mod}; @@ -93,11 +93,14 @@ impl LateLintPass<'_> for ItemsAfterTestModule { if let Some(prev) = mod_pos.checked_sub(1) && let prev = cx.tcx.hir().item(module.item_ids[prev]) && let items_span = last.span.with_lo(test_mod.span.hi()) - && let Some(items) = snippet_opt(cx, items_span) + && let Some(items) = items_span.get_source_text(cx) { diag.multipart_suggestion_with_style( "move the items to before the test module was defined", - vec![(prev.span.shrink_to_hi(), items), (items_span, String::new())], + vec![ + (prev.span.shrink_to_hi(), items.to_owned()), + (items_span, String::new()), + ], Applicability::MachineApplicable, SuggestionStyle::HideCodeAlways, ); diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 225d79aa71d..2f027c11707 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -1,5 +1,3 @@ -//! lint when there is a large size difference between variants on an enum - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_applicability; diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index 4abf7edc9b4..d2bdf194ada 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -3,7 +3,7 @@ use std::{fmt, ops}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::fn_has_unsatisfiable_preds; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { // TODO: Is there a cleaner, robust way to ask this question? // The obvious `LocalDecl::is_user_variable()` panics on "unwrapping cross-crate data", // and that doesn't get us the true name in scope rather than the span text either. - if let Some(name) = snippet_opt(cx, local_span) + if let Some(name) = local_span.get_source_text(cx) && is_ident(&name) { // If the local is an ordinary named variable, diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 752e1326e3e..ccab1e27d3b 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::{get_parent_expr, is_from_proc_macro}; use hir::def_id::DefId; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -143,12 +143,11 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { && !is_from_proc_macro(cx, expr) { span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| { - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "use the associated constant instead", sugg, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); }); } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 4c737371bd2..0bc7fc2dd9d 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::{has_enclosing_paren, Sugg}; use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators}; use rustc_ast::ast::LitKind; @@ -216,7 +216,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span { - let Some(snippet) = snippet_opt(cx, span) else { + let Some(snippet) = span.get_source_text(cx) else { return span; }; if has_enclosing_paren(snippet) { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index ce13a9afef5..2ac06b360be 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -66,8 +66,8 @@ extern crate declare_clippy_lint; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] mod utils; -mod declared_lints; -mod deprecated_lints; +pub mod declared_lints; +pub mod deprecated_lints; // begin lints modules, do not remove this comment, it’s used in `update_lints` mod absolute_paths; @@ -440,7 +440,7 @@ impl RegistrationGroups { } } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum LintCategory { Cargo, Complexity, @@ -479,11 +479,39 @@ impl LintCategory { } } -pub(crate) struct LintInfo { +pub struct LintInfo { /// Double reference to maintain pointer equality - lint: &'static &'static Lint, + pub lint: &'static &'static Lint, category: LintCategory, - explanation: &'static str, + pub explanation: &'static str, + /// e.g. `clippy_lints/src/absolute_paths.rs#43` + pub location: &'static str, + pub version: Option<&'static str>, +} + +impl LintInfo { + /// Returns the lint name in lowercase without the `clippy::` prefix + #[allow(clippy::missing_panics_doc)] + pub fn name_lower(&self) -> String { + self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase() + } + + /// Returns the name of the lint's category in lowercase (`style`, `pedantic`) + pub fn category_str(&self) -> &'static str { + match self.category { + Cargo => "cargo", + Complexity => "complexity", + Correctness => "correctness", + Nursery => "nursery", + Pedantic => "pedantic", + Perf => "perf", + Restriction => "restriction", + Style => "style", + Suspicious => "suspicious", + #[cfg(feature = "internal")] + Internal => "internal", + } + } } pub fn explain(name: &str) -> i32 { @@ -538,14 +566,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_removed(name, reason); } - #[cfg(feature = "internal")] - { - if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new())); - return; - } - } - let format_args_storage = FormatArgsStorage::default(); let format_args = format_args_storage.clone(); store.register_early_pass(move || { diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index 259e4d6c08f..81f2a03fb55 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -1,10 +1,7 @@ -//! Lints concerned with the grouping of digits with underscores in integral or -//! floating-point literal expressions. - use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::numeric_literal::{NumericLiteral, Radix}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; @@ -228,7 +225,7 @@ impl LiteralDigitGrouping { } fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) { - if let Some(src) = snippet_opt(cx, span) + if let Some(src) = span.get_source_text(cx) && let Ok(lit_kind) = LitKind::from_token_lit(lit) && let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) { @@ -442,7 +439,7 @@ impl DecimalLiteralRepresentation { // Lint integral literals. if let Ok(lit_kind) = LitKind::from_token_lit(lit) && let LitKind::Int(val, _) = lit_kind - && let Some(src) = snippet_opt(cx, span) + && let Some(src) = span.get_source_text(cx) && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind) && num_lit.radix == Radix::Decimal && val >= u128::from(self.threshold) diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index eea5f2a94ea..b134af500f5 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -3,7 +3,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{ - implements_trait, implements_trait_with_env, is_copy, make_normalized_projection, + implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection, make_normalized_projection_with_regions, normalize_with_regions, }; use rustc_errors::Applicability; @@ -20,9 +20,10 @@ pub(super) fn check( msrv: &Msrv, enforce_iter_loop_reborrow: bool, ) { - let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else { + let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow, msrv) else { return; }; + if let ty::Array(_, count) = *ty.peel_refs().kind() { if !ty.is_ref() { if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { @@ -109,6 +110,7 @@ fn is_ref_iterable<'tcx>( self_arg: &Expr<'_>, call_expr: &Expr<'_>, enforce_iter_loop_reborrow: bool, + msrv: &Msrv, ) -> Option<(AdjustKind, Ty<'tcx>)> { let typeck = cx.typeck_results(); if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) @@ -128,6 +130,12 @@ fn is_ref_iterable<'tcx>( let self_ty = typeck.expr_ty(self_arg); let self_is_copy = is_copy(cx, self_ty); + if !msrv.meets(msrvs::BOX_INTO_ITER) + && is_type_lang_item(cx, self_ty.peel_refs(), rustc_hir::LangItem::OwnedBox) + { + return None; + } + if adjustments.is_empty() && self_is_copy { // Exact type match, already checked earlier return Some((AdjustKind::None, self_ty)); diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs index fed58f7ff14..e215097142b 100644 --- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -122,8 +122,23 @@ struct BodyVisitor<'a, 'tcx> { /// within a relevant macro. macro_unsafe_blocks: Vec<HirId>, /// When this is >0, it means that the node currently being visited is "within" a - /// macro definition. This is not necessary for correctness, it merely helps reduce the number - /// of spans we need to insert into the map, since only spans from macros are relevant. + /// macro definition. + /// This is used to detect if an expression represents a metavariable. + /// + /// For example, the following pre-expansion code that we want to lint + /// ```ignore + /// macro_rules! m { ($e:expr) => { unsafe { $e; } } } + /// m!(1); + /// ``` + /// would look like this post-expansion code: + /// ```ignore + /// unsafe { /* macro */ + /// 1 /* root */; /* macro */ + /// } + /// ``` + /// Visiting the block and the statement will increment the `expn_depth` so that it is >0, + /// and visiting the expression with a root context while `expn_depth > 0` tells us + /// that it must be a metavariable. expn_depth: u32, cx: &'a LateContext<'tcx>, lint: &'a mut ExprMetavarsInUnsafe, @@ -157,7 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> { && (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id)) { self.macro_unsafe_blocks.push(block.hir_id); + self.expn_depth += 1; walk_block(self, block); + self.expn_depth -= 1; self.macro_unsafe_blocks.pop(); } else if ctxt.is_root() && self.expn_depth > 0 { let unsafe_block = self.macro_unsafe_blocks.last().copied(); diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 25c7e5d38b3..61723aec590 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt}; +use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -68,8 +68,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { header_span, "this function can be simplified using the `async fn` syntax", |diag| { - if let Some(vis_snip) = snippet_opt(cx, *vis_span) - && let Some(header_snip) = snippet_opt(cx, header_span) + if let Some(vis_snip) = vis_span.get_source_text(cx) + && let Some(header_snip) = header_span.get_source_text(cx) && let Some(ret_pos) = position_before_rarrow(&header_snip) && let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output) { @@ -190,6 +190,6 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str, Some((sugg, String::new())) } else { let sugg = "return the output of the future directly"; - snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}"))) + output.span.get_source_text(cx).map(|src| (sugg, format!(" -> {src}"))) } } diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index 6bdc79129a9..9d3ddab60bb 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -1,6 +1,6 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; @@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { // case somebody does that for some reason && (is_infinity(&const_1) && is_neg_infinity(&const_2) || is_neg_infinity(&const_1) && is_infinity(&const_2)) - && let Some(local_snippet) = snippet_opt(cx, first.span) + && let Some(local_snippet) = first.span.get_source_text(cx) { let variant = match (kind.node, lhs_kind.node, rhs_kind.node) { (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Eq) => Variant::ManualIsInfinite, diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs index 1c568b1b74f..11716a539ab 100644 --- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs +++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::visitors::{is_local_used, local_used_once}; use clippy_utils::{is_trait_method, path_to_local_id}; use rustc_errors::Applicability; @@ -107,8 +107,8 @@ impl LateLintPass<'_> for ManualHashOne { finish_expr.span, "manual implementation of `BuildHasher::hash_one`", |diag| { - if let Some(build_hasher) = snippet_opt(cx, build_hasher.span) - && let Some(hashed_value) = snippet_opt(cx, hashed_value.span) + if let Some(build_hasher) = build_hasher.span.get_source_text(cx) + && let Some(hashed_value) = hashed_value.span.get_source_text(cx) { diag.multipart_suggestion( "try", diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 28cfe22835a..6b1d90483cc 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_doc_hidden; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{self, VisibilityKind}; use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; @@ -124,7 +124,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct { |diag| { if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive)) && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter) - && let Some(snippet) = snippet_opt(cx, header_span) + && let Some(snippet) = header_span.get_source_text(cx) { diag.span_suggestion( header_span, @@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { "this seems like a manual implementation of the non-exhaustive pattern", |diag| { let header_span = cx.sess().source_map().span_until_char(enum_span, '{'); - if let Some(snippet) = snippet_opt(cx, header_span) { + if let Some(snippet) = header_span.get_source_text(cx) { diag.span_suggestion( header_span, "add the attribute", diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index 07d4abbf5cd..9afb2b5bc84 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::LitKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -143,8 +143,8 @@ impl LateLintPass<'_> for ManualRangePatterns { pat.span, "this OR pattern can be rewritten using a range", |diag| { - if let Some(min) = snippet_opt(cx, min.span) - && let Some(max) = snippet_opt(cx, max.span) + if let Some(min) = min.span.get_source_text(cx) + && let Some(max) = max.span.get_source_text(cx) { diag.span_suggestion( pat.span, diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index 09f6362b4dd..d4e53f8f74b 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -2,14 +2,13 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; -use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use clippy_utils::{match_def_path, paths, SpanlessEq}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::ExprKind::Assign; use rustc_lint::{LateContext, LateLintPass}; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::Span; @@ -21,16 +20,6 @@ const ACCEPTABLE_METHODS: [&[&str]; 5] = [ &paths::SLICE_INTO, &paths::VEC_DEQUE_ITER, ]; -const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [ - (sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)), - (sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)), - (sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)), - (sym::HashSet, Some(msrvs::HASH_SET_RETAIN)), - (sym::HashMap, Some(msrvs::HASH_MAP_RETAIN)), - (sym::Vec, None), - (sym::VecDeque, None), -]; -const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap]; declare_clippy_lint! { /// ### What it does @@ -265,16 +254,22 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo } fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool { - let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); - ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| { - is_type_diagnostic_item(cx, expr_ty, *ty) - && acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv)) - }) + let ty = cx.typeck_results().expr_ty(expr).peel_refs(); + let required = match get_type_diagnostic_name(cx, ty) { + Some(sym::BinaryHeap) => msrvs::BINARY_HEAP_RETAIN, + Some(sym::BTreeSet) => msrvs::BTREE_SET_RETAIN, + Some(sym::BTreeMap) => msrvs::BTREE_MAP_RETAIN, + Some(sym::HashSet) => msrvs::HASH_SET_RETAIN, + Some(sym::HashMap) => msrvs::HASH_MAP_RETAIN, + Some(sym::Vec | sym::VecDeque) => return true, + _ => return false, + }; + msrv.meets(required) } fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { - let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); - MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty)) + let ty = cx.typeck_results().expr_ty(expr).peel_refs(); + matches!(get_type_diagnostic_name(cx, ty), Some(sym::BTreeMap | sym::HashMap)) } fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) { diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 90cfdecc199..b666e77c09e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -96,7 +96,7 @@ fn check_arm<'tcx>( // collapsing patterns need an explicit field name in struct pattern matching // ex: Struct {x: Some(1)} let replace_msg = if is_innermost_parent_pat_struct { - format!(", prefixed by {}:", snippet(cx, binding_span, "their field name")) + format!(", prefixed by `{}`:", snippet(cx, binding_span, "their field name")) } else { String::new() }; diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs index 2d4c8daf5cb..d5d83df9347 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs @@ -1,6 +1,6 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::contains_return_break_continue_macro; use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg}; @@ -67,11 +67,11 @@ fn check_and_lint<'tcx>( && path_to_local_id(peel_blocks(then_expr), binding_hir_id) && cx.typeck_results().expr_adjustments(then_expr).is_empty() && let Some(ty_name) = find_type_name(cx, ty) - && let Some(or_body_snippet) = snippet_opt(cx, else_expr.span) + && let Some(or_body_snippet) = else_expr.span.get_source_text(cx) && let Some(indent) = indent_of(cx, expr.span) && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some() { - lint(cx, expr, let_expr, ty_name, or_body_snippet, indent); + lint(cx, expr, let_expr, ty_name, &or_body_snippet, indent); } } @@ -110,7 +110,7 @@ fn lint<'tcx>( expr: &Expr<'tcx>, scrutinee: &'tcx Expr<'_>, ty_name: &str, - or_body_snippet: String, + or_body_snippet: &str, indent: usize, ) { let reindented_or_body = reindent_multiline(or_body_snippet.into(), true, Some(indent)); diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 24dea03601c..b6930f7b9d1 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -22,7 +22,7 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; /// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty /// match arms. fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { - if let Some(ff) = span.get_source_text(cx) + if let Some(ff) = span.get_source_range(cx) && let Some(text) = ff.as_str() { text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*") diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index a5df863d800..740cce0a6c2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_lang_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -49,10 +49,12 @@ pub(super) fn check<'tcx>( "case-sensitive file extension comparison", |diag| { diag.help("consider using a case-insensitive comparison instead"); - if let Some(mut recv_source) = snippet_opt(cx, recv.span) { - if !cx.typeck_results().expr_ty(recv).is_ref() { - recv_source = format!("&{recv_source}"); - } + if let Some(recv_source) = recv.span.get_source_text(cx) { + let recv_source = if cx.typeck_results().expr_ty(recv).is_ref() { + recv_source.to_owned() + } else { + format!("&{recv_source}") + }; let suggestion_source = reindent_multiline( format!( diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 2e43d19a699..4fbf661727d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -1,7 +1,7 @@ use super::FILTER_MAP_BOOL_THEN; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::paths::BOOL_THEN; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks}; use rustc_errors::Applicability; @@ -42,9 +42,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & .iter() .filter(|adj| matches!(adj.kind, Adjust::Deref(_))) .count() - && let Some(param_snippet) = snippet_opt(cx, param.span) - && let Some(filter) = snippet_opt(cx, recv.span) - && let Some(map) = snippet_opt(cx, then_body.span) + && let Some(param_snippet) = param.span.get_source_text(cx) + && let Some(filter) = recv.span.get_source_text(cx) + && let Some(map) = then_body.span.get_source_text(cx) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs index 917a8e33eb9..f4840785584 100644 --- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_path_diagnostic_item, sugg}; use rustc_errors::Applicability; @@ -39,7 +39,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) -> } let call_site = expr.span.source_callsite(); - if let Some(snippet) = snippet_opt(cx, call_site) + if let Some(snippet) = call_site.get_source_text(cx) && let snippet_split = snippet.split("::").collect::<Vec<_>>() && let Some((_, elements)) = snippet_split.split_last() { diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs index c6285c87a26..9daad1a8a94 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs @@ -74,7 +74,7 @@ pub(super) fn check<'tcx>( "&" }; - diag.span_suggestion_with_style( + diag.span_suggestion_verbose( span, "using `[]` is clearer and more concise", format!( @@ -82,7 +82,6 @@ pub(super) fn check<'tcx>( snippet_with_applicability(cx, recv.span, "..", &mut applicability) ), applicability, - rustc_errors::SuggestionStyle::ShowAlways, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs index 22d896433f0..40b48ccca5d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,5 +1,3 @@ -//! Lint for `c.is_digit(10)` - use super::IS_DIGIT_ASCII_RADIX; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; diff --git a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs index aa1ec60d434..2dad7fcf3c1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::expr_or_init; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a join_arg.span, "argument to `Path::join` starts with a path separator", |diag| { - let arg_str = snippet_opt(cx, spanned.span).unwrap_or_else(|| "..".to_string()); + let arg_str = snippet(cx, spanned.span, ".."); let no_separator = if sym_str.starts_with('/') { arg_str.replacen('/', "", 1) diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs index b1af0083e65..b1a8e1e5e47 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id}; use rustc_errors::Applicability; @@ -23,11 +23,11 @@ pub(super) fn check<'tcx>( && let ExprKind::Call(err_path, [err_arg]) = or_expr.kind && is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr) && is_ok_wrapping(cx, map_expr) - && let Some(recv_snippet) = snippet_opt(cx, recv.span) - && let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span) + && let Some(recv_snippet) = recv.span.get_source_text(cx) + && let Some(err_arg_snippet) = err_arg.span.get_source_text(cx) && let Some(indent) = indent_of(cx, expr.span) { - let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.into(), true, Some(indent + 4)); + let reindented_err_arg_snippet = reindent_multiline(err_arg_snippet.as_str().into(), true, Some(indent + 4)); span_lint_and_sugg( cx, MANUAL_OK_OR, diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs index f93edded729..11fba35c16e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_from_proc_macro, is_trait_method}; use rustc_errors::Applicability; @@ -31,13 +31,15 @@ pub(super) fn check<'tcx>( && let Res::Def(DefKind::Ctor(_, _), _) = cx.qpath_res(&qpath, path.hir_id) && let ExprKind::Closure(closure) = acc.kind && !is_from_proc_macro(cx, expr) - && let Some(args_snip) = closure.fn_arg_span.and_then(|fn_arg_span| snippet_opt(cx, fn_arg_span)) + && let Some(args_snip) = closure + .fn_arg_span + .and_then(|fn_arg_span| fn_arg_span.get_source_text(cx)) { let init_snip = rest .is_empty() .then_some(first.span) - .and_then(|span| snippet_opt(cx, span)) - .unwrap_or("...".to_owned()); + .and_then(|span| span.get_source_text(cx)) + .map_or_else(|| "...".to_owned(), |src| src.to_owned()); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 1d7b10fe8f0..d7126990edb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2702,10 +2702,10 @@ declare_clippy_lint! { /// } /// }) /// } - /// ``` + /// ``` /// - /// After: - /// ```rust + /// After: + /// ```rust /// use std::{fmt, num::ParseIntError}; /// /// #[derive(Debug)] diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs index e3d78207715..332da722a37 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs @@ -7,7 +7,7 @@ use rustc_span::Span; use super::utils::get_last_chain_binding_hir_id; use super::NEEDLESS_CHARACTER_ITERATION; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{match_def_path, path_to_local_id, peel_blocks}; fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> { @@ -35,7 +35,7 @@ fn handle_expr( && path_to_local_id(receiver, first_param) && let char_arg_ty = cx.typeck_results().expr_ty_adjusted(receiver).peel_refs() && *char_arg_ty.kind() == ty::Char - && let Some(snippet) = snippet_opt(cx, before_chars) + && let Some(snippet) = before_chars.get_source_text(cx) { span_lint_and_sugg( cx, @@ -79,7 +79,7 @@ fn handle_expr( && let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id() && match_def_path(cx, fn_def_id, &["core", "char", "methods", "<impl char>", "is_ascii"]) && path_to_local_id(peels_expr_ref(arg), first_param) - && let Some(snippet) = snippet_opt(cx, before_chars) + && let Some(snippet) = before_chars.get_source_text(cx) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 46b457daf70..f61923e5bf5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -2,7 +2,7 @@ use super::NEEDLESS_COLLECT; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection}; +use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection}; use clippy_utils::{ can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id, CaptureKind, @@ -88,9 +88,10 @@ pub(super) fn check<'tcx>( Node::LetStmt(l) => { if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind && let ty = cx.typeck_results().expr_ty(collect_expr) - && [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList] - .into_iter() - .any(|item| is_type_diagnostic_item(cx, ty, item)) + && matches!( + get_type_diagnostic_name(cx, ty), + Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList) + ) && let iter_ty = cx.typeck_results().expr_ty(iter_expr) && let Some(block) = get_enclosing_block(cx, l.hir_id) && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty)) diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs index eaae8613d44..9f714fdd47b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::path_res; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::local_used_after_expr; use rustc_errors::Applicability; @@ -32,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name expr.span, "derefed type is same as origin", "try", - snippet_opt(cx, recv.span).unwrap(), + recv.span.get_source_text(cx).unwrap().to_owned(), Applicability::MachineApplicable, ); } diff --git a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs index 5f6f027a3b5..cc0d432b799 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_lit_chars_any.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local}; use itertools::Itertools; use rustc_ast::LitKind; @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>( _ => return, } && !is_from_proc_macro(cx, expr) - && let Some(scrutinee_snip) = snippet_opt(cx, scrutinee.span) + && let Some(scrutinee_snip) = scrutinee.span.get_source_text(cx) { // Normalize the char using `map` so `join` doesn't use `Display`, if we don't then // something like `r"\"` will become `'\'`, which is of course invalid diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs index f6184222d8e..64eb8411795 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; @@ -38,11 +38,11 @@ pub(super) fn check( return; }; let both_calls_span = get_call_span.with_hi(call_span.hi()); - if let Some(snippet) = snippet_opt(cx, both_calls_span) - && let Some(arg_snippet) = snippet_opt(cx, arg.span) + if let Some(snippet) = both_calls_span.get_source_text(cx) + && let Some(arg_snippet) = arg.span.get_source_text(cx) { let generics_snippet = if let Some(generics) = path.args - && let Some(generics_snippet) = snippet_opt(cx, generics.span_ext) + && let Some(generics_snippet) = generics.span_ext.get_source_text(cx) { format!("::{generics_snippet}") } else { @@ -63,7 +63,7 @@ pub(super) fn check( suggestion, Applicability::MaybeIncorrect, ); - } else if let Some(caller_snippet) = snippet_opt(cx, get_caller.span) { + } else if let Some(caller_snippet) = get_caller.span.get_source_text(cx) { let full_span = get_caller.span.with_hi(call_span.hi()); span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 70885e46e95..4d18bc7ac77 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -1,7 +1,7 @@ use super::utils::clone_or_copy_needed; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local}; @@ -40,7 +40,7 @@ pub fn check_for_loop_iter( && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent) && let (clone_or_copy_needed, references_to_binding) = clone_or_copy_needed(cx, pat, body) && !clone_or_copy_needed - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { // Issue 12098 // https://github.com/rust-lang/rust-clippy/issues/12098 @@ -100,7 +100,7 @@ pub fn check_for_loop_iter( && implements_trait(cx, collection_ty, into_iterator_trait_id, &[]) && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item") && iter_item_ty == into_iter_item_ty - && let Some(collection_snippet) = snippet_opt(cx, collection.span) + && let Some(collection_snippet) = collection.span.get_source_text(cx) { collection_snippet } else { @@ -122,7 +122,7 @@ pub fn check_for_loop_iter( } else { Applicability::MachineApplicable }; - diag.span_suggestion(expr.span, "use", snippet, applicability); + diag.span_suggestion(expr.span, "use", snippet.to_owned(), applicability); if !references_to_binding.is_empty() { diag.multipart_suggestion( "remove any references to the binding", diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 4429f032605..b84594c0da1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -64,9 +64,9 @@ pub(super) fn check<'tcx>( // but prefer to avoid changing the signature of the function itself. if let hir::ExprKind::MethodCall(.., span) = expr.kind { span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { - diag.span_suggestion( + diag.span_suggestion_verbose( span, - format!("use `{simplify_using}(..)` instead"), + format!("use `{simplify_using}` instead"), format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index fed2b128dcf..69c5bc57e29 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -2,7 +2,7 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{ @@ -133,7 +133,7 @@ fn check_addr_of_expr( && (*referent_ty != receiver_ty || (matches!(referent_ty.kind(), ty::Array(..)) && is_copy(cx, *referent_ty)) || is_cow_into_owned(cx, method_name, method_def_id)) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { if receiver_ty == target_ty && n_target_refs >= n_receiver_refs { span_lint_and_sugg( @@ -167,7 +167,7 @@ fn check_addr_of_expr( parent.span, format!("unnecessary use of `{method_name}`"), "use", - receiver_snippet, + receiver_snippet.to_owned(), Applicability::MachineApplicable, ); } else { @@ -217,7 +217,7 @@ fn check_into_iter_call_arg( && let parent_ty = cx.typeck_results().expr_ty(parent) && implements_trait(cx, parent_ty, iterator_trait_id, &[]) && let Some(item_ty) = get_iterator_item_ty(cx, parent_ty) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; @@ -309,8 +309,8 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb if let Some(parent) = get_parent_expr(cx, expr) && let Some((fn_name, argument_expr)) = get_fn_name_and_arg(cx, parent) && fn_name.as_str() == "split" - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) - && let Some(arg_snippet) = snippet_opt(cx, argument_expr.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) + && let Some(arg_snippet) = argument_expr.span.get_source_text(cx) { // We may end-up here because of an expression like `x.to_string().split(…)` where the type of `x` // implements `AsRef<str>` but does not implement `Deref<Target = str>`. In this case, we have to @@ -405,7 +405,7 @@ fn check_other_call_arg<'tcx>( None } && can_change_type(cx, maybe_arg, receiver_ty) - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + && let Some(receiver_snippet) = receiver.span.get_source_text(cx) { span_lint_and_sugg( cx, @@ -695,7 +695,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx && let arg_ty = arg_ty.peel_refs() // For now we limit this lint to `String` and `Vec`. && (is_str_and_string(cx, arg_ty, original_arg_ty) || is_slice_and_vec(cx, arg_ty, original_arg_ty)) - && let Some(snippet) = snippet_opt(cx, caller.span) + && let Some(snippet) = caller.span.get_source_text(cx) { span_lint_and_sugg( cx, @@ -706,7 +706,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx if original_arg_ty.is_array() { format!("{snippet}.as_slice()") } else { - snippet + snippet.to_owned() }, Applicability::MaybeIncorrect, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs index 3004d9c4233..ee5177d1ffa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind}; @@ -81,8 +81,14 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) { // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`. // Fallback to `..` if we fail getting either snippet. - Some(ty_span) => snippet_opt(cx, elem.span) - .and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}"))) + Some(ty_span) => elem + .span + .get_source_text(cx) + .and_then(|binding_name| { + ty_span + .get_source_text(cx) + .map(|ty_name| format!("{binding_name}: {ty_name}")) + }) .unwrap_or_else(|| "..".to_string()), // Otherwise, we have no explicit type. We can replace with the binding name of the element. None => snippet(cx, elem.span, "..").into_owned(), diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 53fa444e93c..c83e5198c27 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -41,14 +41,14 @@ declare_clippy_lint! { impl_lint_pass!(MinIdentChars => [MIN_IDENT_CHARS]); pub struct MinIdentChars { - allowed_idents_below_min_chars: &'static FxHashSet<String>, + allowed_idents_below_min_chars: FxHashSet<String>, min_ident_chars_threshold: u64, } impl MinIdentChars { pub fn new(conf: &'static Conf) -> Self { Self { - allowed_idents_below_min_chars: &conf.allowed_idents_below_min_chars, + allowed_idents_below_min_chars: conf.allowed_idents_below_min_chars.iter().cloned().collect(), min_ident_chars_threshold: conf.min_ident_chars_threshold, } } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs index 6db03adf44a..33ab94e00a5 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; +use itertools::Itertools; use rustc_ast::ast::{Pat, PatKind}; use rustc_lint::EarlyContext; @@ -45,19 +46,6 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { "you matched a field with a wildcard pattern, consider using `..` instead", ); } else { - let mut normal = vec![]; - - for field in pfields { - match field.pat.kind { - PatKind::Wild => {}, - _ => { - if let Some(n) = snippet_opt(cx, field.span) { - normal.push(n); - } - }, - } - } - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( cx, @@ -65,7 +53,16 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { field.span, "you matched a field with a wildcard pattern, consider using `..` instead", |diag| { - diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", "))); + diag.help(format!( + "try with `{type_name} {{ {}, .. }}`", + pfields + .iter() + .filter_map(|f| match f.pat.kind { + PatKind::Wild => None, + _ => f.span.get_source_text(cx), + }) + .format(", "), + )); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index cdf6645b3df..59f29d242ab 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::def_path_def_ids; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdMap; @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ImportRename { && let Some(name) = self.renames.get(&id) // Remove semicolon since it is not present for nested imports && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';') - && let Some(snip) = snippet_opt(cx, span_without_semi) + && let Some(snip) = span_without_semi.get_source_text(cx) && let Some(import) = match snip.split_once(" as ") { None => Some(snip.as_str()), Some((import, rename)) => { diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 83af9979b9e..f52b3a6a5a1 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -125,14 +125,12 @@ impl<'tcx> MutableKeyType<'tcx> { // generics (because the compiler cannot ensure immutability for unknown types). fn check_ty_(&mut self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { let ty = ty.peel_refs(); - if let ty::Adt(def, args) = ty.kind() { - let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet] - .iter() - .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did())); - if !is_keyed_type { - return; - } - + if let ty::Adt(def, args) = ty.kind() + && matches!( + cx.tcx.get_diagnostic_name(def.did()), + Some(sym::HashMap | sym::BTreeMap | sym::HashSet | sym::BTreeSet) + ) + { let subst_ty = args.type_at(0); if self.interior_mut.is_interior_mut_ty(cx, subst_ty) { span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 853e476a006..38841496458 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -1,7 +1,3 @@ -//! Checks for usage of mutex where an atomic value could be used -//! -//! This lint is **allow** by default - use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::Expr; diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 9cb4fa41c73..df155a7a412 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -1,7 +1,3 @@ -//! Checks for needless boolean results of if-else expressions -//! -//! This lint is **warn** by default - use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index b97cb4579ca..ce97370d4d9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -1,38 +1,3 @@ -//! Checks for continue statements in loops that are redundant. -//! -//! For example, the lint would catch -//! -//! ```rust -//! let mut a = 1; -//! let x = true; -//! -//! while a < 5 { -//! a = 6; -//! if x { -//! // ... -//! } else { -//! continue; -//! } -//! println!("Hello, world"); -//! } -//! ``` -//! -//! And suggest something like this: -//! -//! ```rust -//! let mut a = 1; -//! let x = true; -//! -//! while a < 5 { -//! a = 6; -//! if x { -//! // ... -//! println!("Hello, world"); -//! } -//! } -//! ``` -//! -//! This lint is **warn** by default. use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{indent_of, snippet, snippet_block}; use rustc_ast::ast; diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs index 1d6233d432a..8e14fbf2f80 100644 --- a/src/tools/clippy/clippy_lints/src/needless_if.rs +++ b/src/tools/clippy/clippy_lints/src/needless_if.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher::If; use clippy_utils::is_from_proc_macro; -use clippy_utils::source::{snippet_opt, SpanRangeExt}; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -57,7 +57,7 @@ impl LateLintPass<'_> for NeedlessIf { src.bytes() .all(|ch| matches!(ch, b'{' | b'}') || ch.is_ascii_whitespace()) }) - && let Some(cond_snippet) = snippet_opt(cx, cond.span) + && let Some(cond_snippet) = cond.span.get_source_text(cx) && !is_from_proc_macro(cx, expr) { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 4bfc30fa5cf..46cdb82130f 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{SourceText, SpanRangeExt}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used}; use core::ops::ControlFlow; @@ -236,7 +236,7 @@ fn first_usage<'tcx>( }) } -fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option<String> { +fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> Option<SourceText> { let span = local.span.with_hi(match local.ty { // let <pat>: <ty>; // ~~~~~~~~~~~~~~~ @@ -246,7 +246,7 @@ fn local_snippet_without_semicolon(cx: &LateContext<'_>, local: &LetStmt<'_>) -> None => local.pat.span.hi(), }); - snippet_opt(cx, span) + span.get_source_text(cx) } fn check<'tcx>( @@ -275,7 +275,10 @@ fn check<'tcx>( |diag| { diag.multipart_suggestion( format!("move the declaration `{binding_name}` here"), - vec![(local_stmt.span, String::new()), (assign.lhs_span, let_snippet)], + vec![ + (local_stmt.span, String::new()), + (assign.lhs_span, let_snippet.to_owned()), + ], Applicability::MachineApplicable, ); }, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index a0bbf6b14b2..addb4b1aee8 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_self; use clippy_utils::ptr::get_spans; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; @@ -242,8 +242,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { for (span, suggestion) in clone_spans { diag.span_suggestion( span, - snippet_opt(cx, span) - .map_or("change the call to".into(), |x| format!("change `{x}` to")), + span.get_source_text(cx) + .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), suggestion, Applicability::Unspecified, ); @@ -267,8 +267,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { for (span, suggestion) in clone_spans { diag.span_suggestion( span, - snippet_opt(cx, span) - .map_or("change the call to".into(), |x| format!("change `{x}` to")), + span.get_source_text(cx) + .map_or("change the call to".to_owned(), |src| format!("change `{src}` to")), suggestion, Applicability::Unspecified, ); diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 8232e69db39..b181791699a 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::has_drop; use clippy_utils::{ in_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks, @@ -268,34 +268,31 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) { && reduced.iter().all(|e| e.span.ctxt() == ctxt) { if let ExprKind::Index(..) = &expr.kind { - if is_inside_always_const_context(cx.tcx, expr.hir_id) { - return; + if !is_inside_always_const_context(cx.tcx, expr.hir_id) + && let [arr, func] = &*reduced + && let Some(arr) = arr.span.get_source_text(cx) + && let Some(func) = func.span.get_source_text(cx) + { + span_lint_hir_and_then( + cx, + UNNECESSARY_OPERATION, + expr.hir_id, + stmt.span, + "unnecessary operation", + |diag| { + diag.span_suggestion( + stmt.span, + "statement can be written as", + format!("assert!({arr}.len() > {func});"), + Applicability::MaybeIncorrect, + ); + }, + ); } - let snippet = - if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) { - format!("assert!({arr}.len() > {func});") - } else { - return; - }; - span_lint_hir_and_then( - cx, - UNNECESSARY_OPERATION, - expr.hir_id, - stmt.span, - "unnecessary operation", - |diag| { - diag.span_suggestion( - stmt.span, - "statement can be written as", - snippet, - Applicability::MaybeIncorrect, - ); - }, - ); } else { let mut snippet = String::new(); for e in reduced { - if let Some(snip) = snippet_opt(cx, e.span) { + if let Some(snip) = e.span.get_source_text(cx) { snippet.push_str(&snip); snippet.push(';'); } else { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 6915cd40615..25f547f1a43 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -1,7 +1,3 @@ -//! Checks for usage of const which the type is not `Freeze` (`Cell`-free). -//! -//! This lint is **warn** by default. - use std::ptr; use clippy_config::Conf; @@ -188,7 +184,7 @@ impl_lint_pass!(NonCopyConst<'_> => [DECLARE_INTERIOR_MUTABLE_CONST, BORROW_INTE impl<'tcx> NonCopyConst<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self { Self { - interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability), + interior_mut: InteriorMut::without_pointers(tcx, &conf.ignore_interior_mutability), } } diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs index 2aaf1e6ff46..51ba29d7389 100644 --- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs +++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs @@ -1,7 +1,7 @@ use clippy_config::types::MacroMatcher; use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::{SourceText, SpanRangeExt}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -34,7 +34,7 @@ declare_clippy_lint! { } /// The (callsite span, (open brace, close brace), source snippet) -type MacroInfo = (Span, (char, char), String); +type MacroInfo = (Span, (char, char), SourceText); pub struct MacroBraces { macro_braces: FxHashMap<String, (char, char)>, @@ -94,7 +94,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind && let name = mac_name.as_str() && let Some(&braces) = mac_braces.macro_braces.get(name) - && let Some(snip) = snippet_opt(cx, span_call_site) + && let Some(snip) = span_call_site.get_source_text(cx) // we must check only invocation sites // https://github.com/rust-lang/rust-clippy/issues/7422 && snip.starts_with(&format!("{name}!")) diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index bc71a4790b9..8b9f899d82d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -35,7 +35,7 @@ impl ArithmeticSideEffects { ("f64", FxHashSet::from_iter(["f64"])), ("std::string::String", FxHashSet::from_iter(["str"])), ]); - for [lhs, rhs] in &conf.arithmetic_side_effects_allowed_binary { + for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary { allowed_binary.entry(lhs).or_default().insert(rhs); } for s in &conf.arithmetic_side_effects_allowed { diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 641d881d974..11c97b4ef00 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{binop_traits, eq_expr_value, trait_ref_of_method}; @@ -46,8 +46,8 @@ pub(super) fn check<'tcx>( expr.span, "manual implementation of an assign operation", |diag| { - if let (Some(snip_a), Some(snip_r)) = - (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) + if let Some(snip_a) = assignee.span.get_source_text(cx) + && let Some(snip_r) = rhs.span.get_source_text(cx) { diag.span_suggestion( expr.span, diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index 311cbd050a1..8daedd1c901 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{eq_expr_value, sugg}; use rustc_errors::Applicability; use rustc_hir as hir; @@ -42,7 +42,9 @@ fn lint_misrefactored_assign_op( expr.span, "variable appears on both sides of an assignment operation", |diag| { - if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) { + if let Some(snip_a) = assignee.span.get_source_text(cx) + && let Some(snip_r) = rhs_other.span.get_source_text(cx) + { let a = &sugg::Sugg::hir(cx, assignee, ".."); let r = &sugg::Sugg::hir(cx, rhs, ".."); let long = format!("{snip_a} = {}", sugg::make_binop(op, a, r)); diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 9baecff801f..9e8a821c3f4 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -80,7 +80,7 @@ declare_clippy_lint! { /// ```no_run /// // `n` can be any number, including `i32::MAX`. /// fn foo(n: i32) -> i32 { - /// n + 1 + /// n + 1 /// } /// ``` /// diff --git a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs index ab5fb178700..9d8e833ef6d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs +++ b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -24,8 +24,8 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp e.span, "use of bitwise operator instead of lazy operator between booleans", |diag| { - if let Some(lhs_snip) = snippet_opt(cx, lhs.span) - && let Some(rhs_snip) = snippet_opt(cx, rhs.span) + if let Some(lhs_snip) = lhs.span.get_source_text(cx) + && let Some(rhs_snip) = rhs.span.get_source_text(cx) { let sugg = format!("{lhs_snip} {op_str} {rhs_snip}"); diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs index 607930561e0..861564d5456 100644 --- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs +++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::std_or_core; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -22,8 +22,8 @@ pub(super) fn check<'tcx>( if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left) && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right) - && let Some(left_snip) = snippet_opt(cx, left_var.span) - && let Some(right_snip) = snippet_opt(cx, right_var.span) + && let Some(left_snip) = left_var.span.get_source_text(cx) + && let Some(right_snip) = right_var.span.get_source_text(cx) { let Some(top_crate) = std_or_core(cx) else { return }; span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs index 18bfb588a11..d7fa48c1e38 100644 --- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::path_to_local_id; -use clippy_utils::source::{snippet, snippet_opt}; +use clippy_utils::source::{snippet, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::{LitKind, StrStyle}; use rustc_errors::Applicability; @@ -74,7 +74,7 @@ impl<'tcx> PathbufPushSearcher<'tcx> { && let Some(arg) = self.arg && let ExprKind::Lit(x) = arg.kind && let LitKind::Str(_, StrStyle::Cooked) = x.node - && let Some(s) = snippet_opt(cx, arg.span) + && let Some(s) = arg.span.get_source_text(cx) { Some(format!(" = PathBuf::from({s});")) } else { @@ -84,8 +84,8 @@ impl<'tcx> PathbufPushSearcher<'tcx> { fn gen_pathbuf_join(&self, cx: &LateContext<'_>) -> Option<String> { let arg = self.arg?; - let arg_str = snippet_opt(cx, arg.span)?; - let init_val = snippet_opt(cx, self.init_val.span)?; + let arg_str = arg.span.get_source_text(cx)?; + let init_val = self.init_val.span.get_source_text(cx)?; Some(format!(" = {init_val}.join({arg_str});")) } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 02c05e0aaf9..125f694996c 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -1,7 +1,5 @@ -//! Checks for usage of `&Vec[_]` and `&String`. - use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::expr_sig; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local}; @@ -243,7 +241,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { .chain(result.replacements.iter().map(|r| { ( r.expr_span, - format!("{}{}", snippet_opt(cx, r.self_span).unwrap(), r.replacement), + format!("{}{}", r.self_span.get_source_text(cx).unwrap(), r.replacement), ) })) .collect(), @@ -372,7 +370,7 @@ impl fmt::Display for DerefTyDisplay<'_, '_> { DerefTy::Path => f.write_str("Path"), DerefTy::Slice(hir_ty, ty) => { f.write_char('[')?; - match hir_ty.and_then(|s| snippet_opt(self.0, s)) { + match hir_ty.and_then(|s| s.get_source_text(self.0)) { Some(s) => f.write_str(&s)?, None => ty.fmt(f)?, } @@ -413,6 +411,7 @@ impl<'tcx> DerefTy<'tcx> { } } +#[expect(clippy::too_many_lines)] fn check_fn_args<'cx, 'tcx: 'cx>( cx: &'cx LateContext<'tcx>, fn_sig: ty::FnSig<'tcx>, @@ -488,8 +487,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( return None; } - let ty_name = snippet_opt(cx, ty.span()).unwrap_or_else(|| args.type_at(1).to_string()); - span_lint_hir_and_then( cx, PTR_ARG, @@ -500,7 +497,10 @@ fn check_fn_args<'cx, 'tcx: 'cx>( diag.span_suggestion( hir_ty.span, "change this to", - format!("&{}{ty_name}", mutability.prefix_str()), + match ty.span().get_source_text(cx) { + Some(s) => format!("&{}{s}", mutability.prefix_str()), + None => format!("&{}{}", mutability.prefix_str(), args.type_at(1)), + }, Applicability::Unspecified, ); }, diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index 7c82895d609..87a52cb2186 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -120,8 +120,8 @@ fn build_suggestion( receiver_expr: &Expr<'_>, cast_lhs_expr: &Expr<'_>, ) -> Option<String> { - let receiver = snippet_opt(cx, receiver_expr.span)?; - let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?; + let receiver = receiver_expr.span.get_source_text(cx)?; + let cast_lhs = cast_lhs_expr.span.get_source_text(cx)?; Some(format!("{receiver}.{}({cast_lhs})", method.suggestion())) } diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index a1231c082e6..bfdc1cbeed7 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then}; use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth}; use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths}; use rustc_errors::Applicability; @@ -208,7 +208,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { .assert_crate_local() .lint_root; - if let Some(snip) = snippet_opt(cx, span) + if let Some(snip) = span.get_source_text(cx) && let Some(dot) = snip.rfind('.') { let sugg_span = span.with_lo(span.lo() + BytePos(u32::try_from(dot).unwrap())); diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs index 8f32cf5f2a1..2b4ef21fc48 100644 --- a/src/tools/clippy/clippy_lints/src/reference.rs +++ b/src/tools/clippy/clippy_lints/src/reference.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::source::{snippet_with_applicability, SpanRangeExt}; use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::BytePos; +use rustc_span::{BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -56,11 +56,11 @@ impl EarlyLintPass for DerefAddrOf { { let mut applicability = Applicability::MachineApplicable; let sugg = if e.span.from_expansion() { - if let Some(macro_source) = snippet_opt(cx, e.span) { + if let Some(macro_source) = e.span.get_source_text(cx) { // Remove leading whitespace from the given span // e.g: ` $visitor` turns into `$visitor` - let trim_leading_whitespaces = |span| { - snippet_opt(cx, span) + let trim_leading_whitespaces = |span: Span| { + span.get_source_text(cx) .and_then(|snip| { #[expect(clippy::cast_possible_truncation)] snip.find(|c: char| !c.is_whitespace()) diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index 95014b23043..f6ef02b7c23 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::{def_path_def_ids, path_def_id, paths}; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_hir::def_id::DefIdMap; @@ -122,7 +122,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape }; if let Some((primary, auxiliary, kind)) = parts - && let Some(literal_snippet) = snippet_opt(cx, base) + && let Some(literal_snippet) = base.get_source_text(cx) && let Some(inner) = literal_snippet.get(offset as usize..) // Only convert to native rustc spans if the parsed regex matches the // source snippet exactly, to ensure the span offsets are correct diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 13016cdadb0..5ce091b7a7a 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; -use clippy_utils::source::{snippet_opt, snippet_with_context}; +use clippy_utils::source::{snippet_with_context, SpanRangeExt}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr, Descend}; use clippy_utils::{ @@ -250,20 +250,25 @@ impl<'tcx> LateLintPass<'tcx> for Return { |err| { err.span_label(local.span, "unnecessary `let` binding"); - if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { - if binary_expr_needs_parentheses(initexpr) { - if !has_enclosing_paren(&snippet) { - snippet = format!("({snippet})"); + if let Some(src) = initexpr.span.get_source_text(cx) { + let sugg = if binary_expr_needs_parentheses(initexpr) { + if has_enclosing_paren(&src) { + src.to_owned() + } else { + format!("({src})") } } else if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { - if !has_enclosing_paren(&snippet) { - snippet = format!("({snippet})"); + if has_enclosing_paren(&src) { + format!("{src} as _") + } else { + format!("({src}) as _") } - snippet.push_str(" as _"); - } + } else { + src.to_owned() + }; err.multipart_suggestion( "return the expression directly", - vec![(local.span, String::new()), (retexpr.span, snippet)], + vec![(local.span, String::new()), (retexpr.span, sugg)], Applicability::MachineApplicable, ); } else { @@ -394,7 +399,7 @@ fn check_final_expr<'tcx>( // Returns may be used to turn an expression into a statement in rustc's AST. // This allows the addition of attributes, like `#[allow]` (See: clippy#9361) - // `#[expect(clippy::needless_return)]` needs to be handled separatly to + // `#[expect(clippy::needless_return)]` needs to be handled separately to // actually fulfill the expectation (clippy::#12998) match cx.tcx.hir().attrs(expr.hir_id) { [] => {}, diff --git a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs index e0558429638..44e585953bf 100644 --- a/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs +++ b/src/tools/clippy/clippy_lints/src/single_range_in_vec_init.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::get_trait_def_id; use clippy_utils::higher::VecArgs; use clippy_utils::macros::root_macro_call_first_node; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use rustc_ast::{LitIntType, LitKind, UintTy}; use rustc_errors::Applicability; @@ -92,12 +92,12 @@ impl LateLintPass<'_> for SingleRangeInVecInit { if matches!(lang_item, LangItem::Range) && let ty = cx.typeck_results().expr_ty(start.expr) - && let Some(snippet) = snippet_opt(cx, span) + && let Some(snippet) = span.get_source_text(cx) // `is_from_proc_macro` will skip any `vec![]`. Let's not! && snippet.starts_with(suggested_type.starts_with()) && snippet.ends_with(suggested_type.ends_with()) - && let Some(start_snippet) = snippet_opt(cx, start.span) - && let Some(end_snippet) = snippet_opt(cx, end.span) + && let Some(start_snippet) = start.span.get_source_text(cx) + && let Some(end_snippet) = end.span.get_source_text(cx) { let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx.tcx, &["core", "iter", "Step"]) && implements_trait(cx, ty, step_def_id, &[]) diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index 01f0e3cfadb..7750d8909d3 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -1,6 +1,3 @@ -//! Lint on use of `size_of` or `size_of_val` of T in an expression -//! expecting a count of T - use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 974e21df817..44283a49e84 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -9,7 +9,6 @@ use rustc_hir::def_id::DefId; use rustc_hir::{HirId, Path, PathSegment}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{sym, Span}; @@ -185,9 +184,7 @@ fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool { } = stability.level { let stable = match since { - StableSince::Version(v) => { - msrv.meets(RustcVersion::new(v.major.into(), v.minor.into(), v.patch.into())) - }, + StableSince::Version(v) => msrv.meets(v), StableSince::Current => msrv.current().is_none(), StableSince::Err => false, }; diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index cfc387886dc..6ca4ca000e9 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -190,7 +190,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { } }, ExprKind::Index(target, _idx, _) => { - let e_ty = cx.typeck_results().expr_ty(target).peel_refs(); + let e_ty = cx.typeck_results().expr_ty_adjusted(target).peel_refs(); if e_ty.is_str() || is_type_lang_item(cx, e_ty, LangItem::String) { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 59b74122f30..2e87d36df31 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -1,7 +1,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; -use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability}; +use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt}; use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash}; use core::hash::{Hash, Hasher}; use itertools::Itertools; @@ -206,8 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { let fixed_trait_snippet = unique_traits .iter() - .filter_map(|b| snippet_opt(cx, b.span)) - .collect::<Vec<_>>() + .filter_map(|b| b.span.get_source_text(cx)) .join(" + "); span_lint_and_sugg( @@ -462,9 +461,8 @@ fn rollup_traits( let traits = comparable_bounds .iter() - .filter_map(|&(_, span)| snippet_opt(cx, span)) - .collect::<Vec<_>>(); - let traits = traits.join(" + "); + .filter_map(|&(_, span)| span.get_source_text(cx)) + .join(" + "); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index afc53e6f32d..978d49f09c3 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; -use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; +use clippy_utils::source::{indent_of, reindent_multiline, SourceText, SpanRangeExt}; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind}; use rustc_lint::LateContext; @@ -79,7 +79,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp && block.expr.is_none() && let Some(last_stmt) = block.stmts.iter().last() && let StmtKind::Semi(last_expr) = last_stmt.kind - && let Some(snip) = snippet_opt(cx, last_expr.span) + && let Some(snip) = last_expr.span.get_source_text(cx) { Some((last_stmt.span, snip)) } else { @@ -90,24 +90,24 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp db.span_suggestion( span, "remove the semicolon from the last statement in the block", - sugg, + sugg.as_str(), Applicability::MaybeIncorrect, ); or = "or "; applicability = Applicability::MaybeIncorrect; }); - let arg_snippets: Vec<String> = args_to_recover + let arg_snippets: Vec<_> = args_to_recover .iter() - .filter_map(|arg| snippet_opt(cx, arg.span)) + .filter_map(|arg| arg.span.get_source_text(cx)) .collect(); - let arg_snippets_without_empty_blocks: Vec<String> = args_to_recover + let arg_snippets_without_empty_blocks: Vec<_> = args_to_recover .iter() .filter(|arg| !is_empty_block(arg)) - .filter_map(|arg| snippet_opt(cx, arg.span)) + .filter_map(|arg| arg.span.get_source_text(cx)) .collect(); - if let Some(call_snippet) = snippet_opt(cx, expr.span) { + if let Some(call_snippet) = expr.span.get_source_text(cx) { let sugg = fmt_stmts_and_call( cx, expr, @@ -161,8 +161,8 @@ fn fmt_stmts_and_call( cx: &LateContext<'_>, call_expr: &Expr<'_>, call_snippet: &str, - args_snippets: &[impl AsRef<str>], - non_empty_block_args_snippets: &[impl AsRef<str>], + args_snippets: &[SourceText], + non_empty_block_args_snippets: &[SourceText], ) -> String { let call_expr_indent = indent_of(cx, call_expr.span).unwrap_or(0); let call_snippet_with_replacements = args_snippets diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 448946bd66d..af7abd009d2 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -34,11 +34,18 @@ declare_clippy_lint! { /// ```rust,ignore /// use std::io; /// fn foo<W: io::Write>(w: &mut W) -> io::Result<()> { - /// // must be `w.write_all(b"foo")?;` /// w.write(b"foo")?; /// Ok(()) /// } /// ``` + /// Use instead: + /// ```rust,ignore + /// use std::io; + /// fn foo<W: io::Write>(w: &mut W) -> io::Result<()> { + /// w.write_all(b"foo")?; + /// Ok(()) + /// } + /// ``` #[clippy::version = "pre 1.29.0"] pub UNUSED_IO_AMOUNT, correctness, @@ -235,7 +242,7 @@ fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { /// If `expr` is an (e).await, return the inner expression "e" that's being /// waited on. Otherwise return None. -fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> { +fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { if let ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { if let ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { if matches!( diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs index b70aa768b46..65f431d338b 100644 --- a/src/tools/clippy/clippy_lints/src/unused_unit.rs +++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{position_before_rarrow, snippet_opt}; +use clippy_utils::source::{position_before_rarrow, SpanRangeExt}; use rustc_ast::visit::FnKind; use rustc_ast::{ast, ClosureBinder}; use rustc_errors::Applicability; @@ -128,15 +128,17 @@ fn is_unit_expr(expr: &ast::Expr) -> bool { fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) { let (ret_span, appl) = - snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| { - position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { - ( - #[expect(clippy::cast_possible_truncation)] - ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), - Applicability::MachineApplicable, - ) - }) - }); + span.with_hi(ty.span.hi()) + .get_source_text(cx) + .map_or((ty.span, Applicability::MaybeIncorrect), |src| { + position_before_rarrow(&src).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| { + ( + #[expect(clippy::cast_possible_truncation)] + ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)), + Applicability::MachineApplicable, + ) + }) + }); span_lint_and_sugg( cx, UNUSED_UNIT, diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index c0d9bcdd259..0b4ea0752b6 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -89,15 +89,15 @@ enum UnwrappableKind { impl UnwrappableKind { fn success_variant_pattern(self) -> &'static str { match self { - UnwrappableKind::Option => "Some(..)", - UnwrappableKind::Result => "Ok(..)", + UnwrappableKind::Option => "Some(<item>)", + UnwrappableKind::Result => "Ok(<item>)", } } fn error_variant_pattern(self) -> &'static str { match self { UnwrappableKind::Option => "None", - UnwrappableKind::Result => "Err(..)", + UnwrappableKind::Result => "Err(<item>)", } } } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 93785b45c27..5da48f4f7fb 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -229,7 +229,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() && same_type_and_consts(ty, impl_ty) // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that - // the lifetime parameters of `ty` are ellided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in + // the lifetime parameters of `ty` are elided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in // which case we must still trigger the lint. && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty)) { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 316c1f32d3a..0cce45290cf 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -1,6 +1,3 @@ -//! A group of attributes that can be attached to Rust code in order -//! to generate a clippy lint detecting said code automatically. - use clippy_utils::{get_attr, higher}; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::LitIntType; diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs index 5acfd35fd6a..f50ce6c99de 100644 --- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs @@ -1,5 +1,5 @@ use clippy_utils::macros::FormatArgsStorage; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use itertools::Itertools; use rustc_ast::{Crate, Expr, ExprKind, FormatArgs}; use rustc_data_structures::fx::FxHashMap; @@ -75,38 +75,21 @@ fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool { // `format!("{} {} {c}", "one", "two", c = "three")` // ^^ ^^ ^^^^^^ - let between_spans = once(args.span) + !once(args.span) .chain(argument_span) .tuple_windows() - .map(|(start, end)| start.between(end)); - - for between_span in between_spans { - let mut seen_comma = false; - - let Some(snippet) = snippet_opt(cx, between_span) else { - return true; - }; - for token in tokenize(&snippet) { - match token.kind { - TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {}, - TokenKind::Comma if !seen_comma => seen_comma = true, - // named arguments, `start_val, name = end_val` - // ^^^^^^^^^ between_span - TokenKind::Ident | TokenKind::Eq if seen_comma => {}, - // An unexpected token usually indicates that we crossed a macro boundary - // - // `println!(some_proc_macro!("input {}"), a)` - // ^^^ between_span - // `println!("{}", val!(x))` - // ^^^^^^^ between_span - _ => return true, - } - } - - if !seen_comma { - return true; - } - } - - false + .map(|(start, end)| start.between(end)) + .all(|sp| { + sp.check_source_text(cx, |src| { + // text should be either `, name` or `, name =` + let mut iter = tokenize(src).filter(|t| { + !matches!( + t.kind, + TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace + ) + }); + iter.next().is_some_and(|t| matches!(t.kind, TokenKind::Comma)) + && iter.all(|t| matches!(t.kind, TokenKind::Ident | TokenKind::Eq)) + }) + }) } diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs index 1d294c2944b..f662c7651f6 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -3,7 +3,6 @@ pub mod collapsible_calls; pub mod interning_defined_symbol; pub mod invalid_paths; pub mod lint_without_lint_pass; -pub mod metadata_collector; pub mod msrv_attr_impl; pub mod outer_expn_data_pass; pub mod produce_ice; diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index df342e48d63..20526113d69 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -9,7 +9,6 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; @@ -92,7 +91,12 @@ pub struct LintWithoutLintPass { registered_lints: FxHashSet<Symbol>, } -impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]); +impl_lint_pass!(LintWithoutLintPass => [ + DEFAULT_LINT, + LINT_WITHOUT_LINT_PASS, + INVALID_CLIPPY_VERSION_ATTRIBUTE, + MISSING_CLIPPY_VERSION_ATTRIBUTE, +]); impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -220,7 +224,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<' return; } - if RustcVersion::parse(value.as_str()).is_err() { + if rustc_attr::parse_version(value).is_none() { span_lint_and_help( cx, INVALID_CLIPPY_VERSION_ATTRIBUTE, diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs deleted file mode 100644 index 57f45aa3e48..00000000000 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ /dev/null @@ -1,1078 +0,0 @@ -//! This lint is used to collect metadata about clippy lints. This metadata is exported as a json -//! file and then used to generate the [clippy lint list](https://rust-lang.github.io/rust-clippy/master/index.html) -//! -//! This module and therefore the entire lint is guarded by a feature flag called `internal` -//! -//! The module transforms all lint names to ascii lowercase to ensure that we don't have mismatches -//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such -//! a simple mistake) - -use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type}; -use clippy_config::{get_configuration_metadata, ClippyConfiguration}; - -use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::{match_type, walk_ptrs_ty_depth}; -use clippy_utils::{last_path_segment, match_function_call, match_path, paths}; -use itertools::Itertools; -use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def::DefKind; -use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, intravisit, Closure, ExprKind, Item, ItemKind, Mutability, QPath}; -use rustc_lint::{unerased_lint_store, CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId}; -use rustc_middle::hir::nested_filter; -use rustc_session::impl_lint_pass; -use rustc_span::symbol::Ident; -use rustc_span::{sym, Loc, Span, Symbol}; -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; -use std::collections::{BTreeSet, BinaryHeap}; -use std::fmt::Write as _; -use std::fs::{self, File}; -use std::io::prelude::*; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::{env, fmt}; - -/// This is the json output file of the lint collector. -const JSON_OUTPUT_FILE: &str = "../util/gh-pages/lints.json"; -/// This is the markdown output file of the lint collector. -const MARKDOWN_OUTPUT_FILE: &str = "../book/src/lint_configuration.md"; -/// These groups will be ignored by the lint group matcher. This is useful for collections like -/// `clippy::all` -const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"]; -/// Lints within this group will be excluded from the collection. These groups -/// have to be defined without the `clippy::` prefix. -const EXCLUDED_LINT_GROUPS: [&str; 1] = ["internal"]; -/// Collected deprecated lint will be assigned to this group in the JSON output -const DEPRECATED_LINT_GROUP_STR: &str = "deprecated"; -/// This is the lint level for deprecated lints that will be displayed in the lint list -const DEPRECATED_LINT_LEVEL: &str = "none"; -/// This array holds Clippy's lint groups with their corresponding default lint level. The -/// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`. -const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[ - ("correctness", "deny"), - ("suspicious", "warn"), - ("restriction", "allow"), - ("style", "warn"), - ("pedantic", "allow"), - ("complexity", "warn"), - ("perf", "warn"), - ("cargo", "allow"), - ("nursery", "allow"), -]; -/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed -/// to only keep the actual lint group in the output. -const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::"; -const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [ - &["clippy_utils", "diagnostics", "span_lint"], - &["clippy_utils", "diagnostics", "span_lint_and_help"], - &["clippy_utils", "diagnostics", "span_lint_and_note"], - &["clippy_utils", "diagnostics", "span_lint_hir"], - &["clippy_utils", "diagnostics", "span_lint_and_sugg"], - &["clippy_utils", "diagnostics", "span_lint_and_then"], - &["clippy_utils", "diagnostics", "span_lint_hir_and_then"], -]; -const SUGGESTION_DIAG_METHODS: [(&str, bool); 9] = [ - ("span_suggestion", false), - ("span_suggestion_short", false), - ("span_suggestion_verbose", false), - ("span_suggestion_hidden", false), - ("tool_only_span_suggestion", false), - ("multipart_suggestion", true), - ("multipart_suggestions", true), - ("tool_only_multipart_suggestion", true), - ("span_suggestions", true), -]; - -/// The index of the applicability name of `paths::APPLICABILITY_VALUES` -const APPLICABILITY_NAME_INDEX: usize = 2; -/// This applicability will be set for unresolved applicability values. -const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved"; -/// The version that will be displayed if none has been defined -const VERSION_DEFAULT_STR: &str = "Unknown"; - -const CHANGELOG_PATH: &str = "../CHANGELOG.md"; - -declare_clippy_lint! { - /// ### What it does - /// Collects metadata about clippy lints for the website. - /// - /// This lint will be used to report problems of syntax parsing. You should hopefully never - /// see this but never say never I guess ^^ - /// - /// ### Why is this bad? - /// This is not a bad thing but definitely a hacky way to do it. See - /// issue [#4310](https://github.com/rust-lang/rust-clippy/issues/4310) for a discussion - /// about the implementation. - /// - /// ### Known problems - /// Hopefully none. It would be pretty uncool to have a problem here :) - /// - /// ### Example output - /// ```json,ignore - /// { - /// "id": "metadata_collector", - /// "id_span": { - /// "path": "clippy_lints/src/utils/internal_lints/metadata_collector.rs", - /// "line": 1 - /// }, - /// "group": "clippy::internal", - /// "docs": " ### What it does\nCollects metadata about clippy lints for the website. [...] " - /// } - /// ``` - #[clippy::version = "1.56.0"] - pub METADATA_COLLECTOR, - internal, - "A busy bee collection metadata about lints" -} - -impl_lint_pass!(MetadataCollector => [METADATA_COLLECTOR]); - -#[allow(clippy::module_name_repetitions)] -#[derive(Debug, Clone)] -pub struct MetadataCollector { - /// All collected lints - /// - /// We use a Heap here to have the lints added in alphabetic order in the export - lints: BinaryHeap<LintMetadata>, - applicability_info: FxHashMap<String, ApplicabilityInfo>, - config: Vec<ClippyConfiguration>, - clippy_project_root: PathBuf, -} - -impl MetadataCollector { - pub fn new() -> Self { - Self { - lints: BinaryHeap::<LintMetadata>::default(), - applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(), - config: get_configuration_metadata(), - clippy_project_root: env::current_dir() - .expect("failed to get current dir") - .ancestors() - .nth(1) - .expect("failed to get project root") - .to_path_buf(), - } - } - - fn get_lint_configs(&self, lint_name: &str) -> Option<String> { - self.config - .iter() - .filter(|config| config.lints.iter().any(|&lint| lint == lint_name)) - .map(ToString::to_string) - .reduce(|acc, x| acc + "\n\n" + &x) - .map(|configurations| { - format!( - r#" -### Configuration -This lint has the following configuration variables: - -{configurations} -"# - ) - }) - } - - fn configs_to_markdown(&self, map_fn: fn(&ClippyConfiguration) -> String) -> String { - self.config - .iter() - .filter(|config| config.deprecation_reason.is_none()) - .filter(|config| !config.lints.is_empty()) - .map(map_fn) - .join("\n") - } - - fn get_markdown_docs(&self) -> String { - format!( - r#"# Lint Configuration Options - -The following list shows each configuration option, along with a description, its default value, an example -and lints affected. - ---- - -{}"#, - self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph), - ) - } -} - -impl Drop for MetadataCollector { - /// You might ask: How hacky is this? - /// My answer: YES - fn drop(&mut self) { - // The metadata collector gets dropped twice, this makes sure that we only write - // when the list is full - if self.lints.is_empty() { - return; - } - - let mut applicability_info = std::mem::take(&mut self.applicability_info); - - // Add deprecated lints - self.lints.extend( - crate::deprecated_lints::DEPRECATED - .iter() - .zip(crate::deprecated_lints::DEPRECATED_VERSION) - .filter_map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), - ); - // Mapping the final data - let mut lints = std::mem::take(&mut self.lints).into_sorted_vec(); - for x in &mut lints { - x.applicability = Some(applicability_info.remove(&x.id).unwrap_or_default()); - replace_produces(&x.id, &mut x.docs, &self.clippy_project_root); - } - - collect_renames(&mut lints); - - // Outputting json - fs::write(JSON_OUTPUT_FILE, serde_json::to_string_pretty(&lints).unwrap()).unwrap(); - - // Outputting markdown - let mut file = File::create(MARKDOWN_OUTPUT_FILE).unwrap(); - writeln!( - file, - "<!-- -This file is generated by `cargo collect-metadata`. -Please use that command to update the file and do not edit it by hand. ---> - -{}", - self.get_markdown_docs(), - ) - .unwrap(); - - // Write configuration links to CHANGELOG.md - let changelog = fs::read_to_string(CHANGELOG_PATH).unwrap(); - let mut changelog_file = File::create(CHANGELOG_PATH).unwrap(); - let position = changelog - .find("<!-- begin autogenerated links to configuration documentation -->") - .unwrap(); - writeln!( - changelog_file, - "{}<!-- begin autogenerated links to configuration documentation -->\n{}\n<!-- end autogenerated links to configuration documentation -->", - &changelog[..position], - self.configs_to_markdown(ClippyConfiguration::to_markdown_link) - ) - .unwrap(); - } -} - -#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)] -struct LintMetadata { - id: String, - id_span: Option<SerializableSpan>, - group: String, - level: String, - docs: String, - version: String, - /// This field is only used in the output and will only be - /// mapped shortly before the actual output. - applicability: Option<ApplicabilityInfo>, - /// All the past names of lints which have been renamed. - #[serde(skip_serializing_if = "BTreeSet::is_empty")] - former_ids: BTreeSet<String>, -} - -impl LintMetadata { - fn new( - id: String, - id_span: SerializableSpan, - group: String, - level: &'static str, - version: String, - docs: String, - ) -> Self { - Self { - id, - id_span: Some(id_span), - group, - level: level.to_string(), - version, - docs, - applicability: None, - former_ids: BTreeSet::new(), - } - } - - fn new_deprecated(name: &str, reason: &str, version: &str) -> Option<Self> { - // The reason starts with a lowercase letter and end without a period. - // This needs to be fixed for the website. - let mut reason = reason.to_owned(); - if let Some(reason) = reason.get_mut(0..1) { - reason.make_ascii_uppercase(); - } - name.strip_prefix("clippy::").map(|name| Self { - id: name.into(), - id_span: None, - group: DEPRECATED_LINT_GROUP_STR.into(), - level: DEPRECATED_LINT_LEVEL.into(), - version: version.into(), - docs: format!( - "### What it does\n\n\ - Nothing. This lint has been deprecated\n\n\ - ### Deprecation reason\n\n{reason}.\n", - ), - applicability: None, - former_ids: BTreeSet::new(), - }) - } -} - -fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Path) { - let mut doc_lines = docs.lines().map(ToString::to_string).collect::<Vec<_>>(); - let mut lines = doc_lines.iter_mut(); - - 'outer: loop { - // Find the start of the example - - // ```rust - loop { - match lines.next() { - Some(line) if line.trim_start().starts_with("```rust") => { - if line.contains("ignore") || line.contains("no_run") { - // A {{produces}} marker may have been put on a ignored code block by mistake, - // just seek to the end of the code block and continue checking. - if lines.any(|line| line.trim_start().starts_with("```")) { - continue; - } - - panic!("lint `{lint_name}` has an unterminated code block") - } - - break; - }, - Some(line) if line.trim_start() == "{{produces}}" => { - panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block") - }, - Some(line) => { - let line = line.trim(); - // These are the two most common markers of the corrections section - if line.eq_ignore_ascii_case("Use instead:") || line.eq_ignore_ascii_case("Could be written as:") { - break 'outer; - } - }, - None => break 'outer, - } - } - - // Collect the example - let mut example = Vec::new(); - loop { - match lines.next() { - Some(line) if line.trim_start() == "```" => break, - Some(line) => example.push(line), - None => panic!("lint `{lint_name}` has an unterminated code block"), - } - } - - // Find the {{produces}} and attempt to generate the output - loop { - match lines.next() { - Some(line) if line.is_empty() => {}, - Some(line) if line.trim() == "{{produces}}" => { - let output = get_lint_output(lint_name, &example, clippy_project_root); - line.replace_range( - .., - &format!( - "<details>\ - <summary>Produces</summary>\n\ - \n\ - ```text\n\ - {output}\n\ - ```\n\ - </details>" - ), - ); - - break; - }, - // No {{produces}}, we can move on to the next example - Some(_) => break, - None => break 'outer, - } - } - } - - *docs = cleanup_docs(&doc_lines); -} - -fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root: &Path) -> String { - let dir = tempfile::tempdir().unwrap_or_else(|e| panic!("failed to create temp dir: {e}")); - let file = dir.path().join("lint_example.rs"); - - let mut source = String::new(); - let unhidden = example - .iter() - .map(|line| line.trim_start().strip_prefix("# ").unwrap_or(line)); - - // Get any attributes - let mut lines = unhidden.peekable(); - while let Some(line) = lines.peek() { - if line.starts_with("#!") { - source.push_str(line); - source.push('\n'); - lines.next(); - } else { - break; - } - } - - let needs_main = !example.iter().any(|line| line.contains("fn main")); - if needs_main { - source.push_str("fn main() {\n"); - } - - for line in lines { - source.push_str(line); - source.push('\n'); - } - - if needs_main { - source.push_str("}\n"); - } - - if let Err(e) = fs::write(&file, &source) { - panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy()); - } - - let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}"); - - let mut cmd = Command::new(env::var("CARGO").unwrap_or("cargo".into())); - - cmd.current_dir(clippy_project_root) - .env("CARGO_INCREMENTAL", "0") - .env("CLIPPY_ARGS", "") - .env("CLIPPY_DISABLE_DOCS_LINKS", "1") - // We need to disable this to enable all lints - .env("ENABLE_METADATA_COLLECTION", "0") - .args(["run", "--bin", "clippy-driver"]) - .args(["--target-dir", "./clippy_lints/target"]) - .args(["--", "--error-format=json"]) - .args(["--edition", "2021"]) - .arg("-Cdebuginfo=0") - .args(["-A", "clippy::all"]) - .args(["-W", &prefixed_name]) - .args(["-L", "./target/debug"]) - .args(["-Z", "no-codegen"]); - - let output = cmd - .arg(file.as_path()) - .output() - .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}")); - - let tmp_file_path = file.to_string_lossy(); - let stderr = std::str::from_utf8(&output.stderr).unwrap(); - let msgs = stderr - .lines() - .filter(|line| line.starts_with('{')) - .map(|line| serde_json::from_str(line).unwrap()) - .collect::<Vec<serde_json::Value>>(); - - let mut rendered = String::new(); - let iter = msgs - .iter() - .filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s == &prefixed_name)); - - for message in iter { - let rendered_part = message["rendered"].as_str().expect("rendered field should exist"); - rendered.push_str(rendered_part); - } - - if rendered.is_empty() { - let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); - let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect(); - panic!( - "did not find lint `{lint_name}` in output of example, got:\n{}\n{}", - non_json.join("\n"), - rendered.join("\n") - ); - } - - // The reader doesn't need to see `/tmp/.tmpfiy2Qd/lint_example.rs` :) - rendered.trim_end().replace(&*tmp_file_path, "lint_example.rs") -} - -#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)] -struct SerializableSpan { - path: String, - line: usize, -} - -impl fmt::Display for SerializableSpan { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}", self.path.rsplit('/').next().unwrap_or_default(), self.line) - } -} - -impl SerializableSpan { - fn from_item(cx: &LateContext<'_>, item: &Item<'_>) -> Self { - Self::from_span(cx, item.ident.span) - } - - fn from_span(cx: &LateContext<'_>, span: Span) -> Self { - let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo()); - - Self { - path: format!("{}", loc.file.name.prefer_remapped_unconditionaly()), - line: loc.line, - } - } -} - -#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)] -struct ApplicabilityInfo { - /// Indicates if any of the lint emissions uses multiple spans. This is related to - /// [rustfix#141](https://github.com/rust-lang/rustfix/issues/141) as such suggestions can - /// currently not be applied automatically. - is_multi_part_suggestion: bool, - applicability: Option<usize>, -} - -impl Serialize for ApplicabilityInfo { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?; - s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?; - if let Some(index) = self.applicability { - s.serialize_field( - "applicability", - &paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX], - )?; - } else { - s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?; - } - s.end() - } -} - -// ================================================================== -// Lint pass -// ================================================================== -impl<'hir> LateLintPass<'hir> for MetadataCollector { - /// Collecting lint declarations like: - /// ```rust, ignore - /// declare_clippy_lint! { - /// /// ### What it does - /// /// Something IDK. - /// pub SOME_LINT, - /// internal, - /// "Who am I?" - /// } - /// ``` - fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) { - if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { - // Normal lint - if is_lint_ref_type(cx, ty) - // item validation - // disallow check - && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase() - // metadata extraction - && let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item) - && let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item) - { - if let Some(configuration_section) = self.get_lint_configs(&lint_name) { - raw_docs.push_str(&configuration_section); - } - let version = get_lint_version(cx, item); - - self.lints.push(LintMetadata::new( - lint_name, - SerializableSpan::from_item(cx, item), - group, - level, - version, - raw_docs, - )); - } - } - } - - /// Collecting constant applicability from the actual lint emissions - /// - /// Example: - /// ```rust, ignore - /// span_lint_and_sugg( - /// cx, - /// SOME_LINT, - /// item.span, - /// "Le lint message", - /// "Here comes help:", - /// "#![allow(clippy::all)]", - /// Applicability::MachineApplicable, // <-- Extracts this constant value - /// ); - /// ``` - fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) { - if let Some(args) = match_lint_emission(cx, expr) { - let emission_info = extract_emission_info(cx, args); - if emission_info.is_empty() { - // See: - // - src/misc.rs:734:9 - // - src/methods/mod.rs:3545:13 - // - src/methods/mod.rs:3496:13 - // We are basically unable to resolve the lint name itself. - return; - } - - for (lint_name, applicability, is_multi_part) in emission_info { - let app_info = self.applicability_info.entry(lint_name).or_default(); - app_info.applicability = applicability; - app_info.is_multi_part_suggestion = is_multi_part; - } - } - } -} - -// ================================================================== -// Lint definition extraction -// ================================================================== -fn sym_to_string(sym: Symbol) -> String { - sym.as_str().to_string() -} - -fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { - extract_attr_docs(cx, item).or_else(|| { - lint_collection_error_item(cx, item, "could not collect the lint documentation"); - None - }) -} - -/// This function collects all documentation that has been added to an item using -/// `#[doc = r""]` attributes. Several attributes are aggravated using line breaks -/// -/// ```ignore -/// #[doc = r"Hello world!"] -/// #[doc = r"=^.^="] -/// struct SomeItem {} -/// ``` -/// -/// Would result in `Hello world!\n=^.^=\n` -fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> { - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str); - - if let Some(line) = lines.next() { - let raw_docs = lines.fold(String::from(line.as_str()) + "\n", |s, line| s + line.as_str() + "\n"); - return Some(raw_docs); - } - - None -} - -/// This function may modify the doc comment to ensure that the string can be displayed using a -/// markdown viewer in Clippy's lint list. The following modifications could be applied: -/// * Removal of leading space after a new line. (Important to display tables) -/// * Ensures that code blocks only contain language information -fn cleanup_docs(docs_collection: &Vec<String>) -> String { - let mut in_code_block = false; - let mut is_code_block_rust = false; - - let mut docs = String::new(); - for line in docs_collection { - // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :) - if is_code_block_rust && line.trim_start().starts_with("# ") { - continue; - } - - // The line should be represented in the lint list, even if it's just an empty line - docs.push('\n'); - if let Some(info) = line.trim_start().strip_prefix("```") { - in_code_block = !in_code_block; - is_code_block_rust = false; - if in_code_block { - let lang = info - .trim() - .split(',') - // remove rustdoc directives - .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic")) - // if no language is present, fill in "rust" - .unwrap_or("rust"); - let len_diff = line.len() - line.trim_start().len(); - if len_diff != 0 { - // We put back the indentation. - docs.push_str(&line[..len_diff]); - } - docs.push_str("```"); - docs.push_str(lang); - - is_code_block_rust = lang == "rust"; - continue; - } - } - // This removes the leading space that the macro translation introduces - if let Some(stripped_doc) = line.strip_prefix(' ') { - docs.push_str(stripped_doc); - } else if !line.is_empty() { - docs.push_str(line); - } - } - - docs -} - -fn get_lint_version(cx: &LateContext<'_>, item: &Item<'_>) -> String { - extract_clippy_version_value(cx, item).map_or_else( - || VERSION_DEFAULT_STR.to_string(), - |version| version.as_str().to_string(), - ) -} - -fn get_lint_group_and_level_or_lint( - cx: &LateContext<'_>, - lint_name: &str, - item: &Item<'_>, -) -> Option<(String, &'static str)> { - let result = unerased_lint_store(cx.tcx.sess).check_lint_name( - lint_name, - Some(sym::clippy), - &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(), - ); - if let CheckLintNameResult::Tool(lint_lst, None) = result { - if let Some(group) = get_lint_group(cx, lint_lst[0]) { - if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) { - return None; - } - - if let Some(level) = get_lint_level_from_group(&group) { - Some((group, level)) - } else { - lint_collection_error_item( - cx, - item, - &format!("Unable to determine lint level for found group `{group}`"), - ); - None - } - } else { - lint_collection_error_item(cx, item, "Unable to determine lint group"); - None - } - } else { - lint_collection_error_item(cx, item, "Unable to find lint in lint_store"); - None - } -} - -fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> { - for (group_name, lints, _) in unerased_lint_store(cx.tcx.sess).get_lint_groups() { - if IGNORED_LINT_GROUPS.contains(&group_name) { - continue; - } - - if lints.iter().any(|group_lint| *group_lint == lint_id) { - let group = group_name.strip_prefix(CLIPPY_LINT_GROUP_PREFIX).unwrap_or(group_name); - return Some((*group).to_string()); - } - } - - None -} - -fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> { - DEFAULT_LINT_LEVELS - .iter() - .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level)) -} - -fn collect_renames(lints: &mut Vec<LintMetadata>) { - for lint in lints { - let mut collected = String::new(); - let mut names = vec![lint.id.clone()]; - - loop { - if let Some(lint_name) = names.pop() { - for (k, v) in crate::deprecated_lints::RENAMED { - if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) - && name == lint_name - && let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX) - { - lint.former_ids.insert(past_name.to_owned()); - writeln!(collected, "* `{past_name}`").unwrap(); - names.push(past_name.to_string()); - } - } - - continue; - } - - break; - } - - if !collected.is_empty() { - write!( - &mut lint.docs, - r#" -### Past names - -{collected} -"# - ) - .unwrap(); - } - } -} - -// ================================================================== -// Lint emission -// ================================================================== -fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &str) { - span_lint( - cx, - METADATA_COLLECTOR, - item.ident.span, - format!("metadata collection error for `{}`: {message}", item.ident.name), - ); -} - -// ================================================================== -// Applicability -// ================================================================== -/// This function checks if a given expression is equal to a simple lint emission function call. -/// It will return the function arguments if the emission matched any function. -fn match_lint_emission<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) -> Option<&'hir [hir::Expr<'hir>]> { - LINT_EMISSION_FUNCTIONS - .iter() - .find_map(|emission_fn| match_function_call(cx, expr, emission_fn)) -} - -fn take_higher_applicability(a: Option<usize>, b: Option<usize>) -> Option<usize> { - a.map_or(b, |a| a.max(b.unwrap_or_default()).into()) -} - -fn extract_emission_info<'hir>( - cx: &LateContext<'hir>, - args: &'hir [hir::Expr<'hir>], -) -> Vec<(String, Option<usize>, bool)> { - let mut lints = Vec::new(); - let mut applicability = None; - let mut multi_part = false; - - for arg in args { - let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg)); - - if match_type(cx, arg_ty, &paths::LINT) { - // If we found the lint arg, extract the lint name - let mut resolved_lints = resolve_lints(cx, arg); - lints.append(&mut resolved_lints); - } else if match_type(cx, arg_ty, &paths::APPLICABILITY) { - applicability = resolve_applicability(cx, arg); - } else if arg_ty.is_closure() { - multi_part |= check_is_multi_part(cx, arg); - applicability = applicability.or_else(|| resolve_applicability(cx, arg)); - } - } - - lints - .into_iter() - .map(|lint_name| (lint_name, applicability, multi_part)) - .collect() -} - -/// Resolves the possible lints that this expression could reference -fn resolve_lints<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Vec<String> { - let mut resolver = LintResolver::new(cx); - resolver.visit_expr(expr); - resolver.lints -} - -/// This function tries to resolve the linked applicability to the given expression. -fn resolve_applicability<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<usize> { - let mut resolver = ApplicabilityResolver::new(cx); - resolver.visit_expr(expr); - resolver.complete() -} - -fn check_is_multi_part<'hir>(cx: &LateContext<'hir>, closure_expr: &'hir hir::Expr<'hir>) -> bool { - if let ExprKind::Closure(&Closure { body, .. }) = closure_expr.kind { - let mut scanner = IsMultiSpanScanner::new(cx); - intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body)); - return scanner.is_multi_part(); - } else if let Some(local) = get_parent_local(cx, closure_expr) { - if let Some(local_init) = local.init { - return check_is_multi_part(cx, local_init); - } - } - - false -} - -struct LintResolver<'a, 'hir> { - cx: &'a LateContext<'hir>, - lints: Vec<String>, -} - -impl<'a, 'hir> LintResolver<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - lints: Vec::<String>::default(), - } - } -} - -impl<'a, 'hir> Visitor<'hir> for LintResolver<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - if let ExprKind::Path(qpath) = &expr.kind - && let QPath::Resolved(_, path) = qpath - && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)) - && match_type(self.cx, expr_ty, &paths::LINT) - { - if let hir::def::Res::Def(DefKind::Static { .. }, _) = path.res { - let lint_name = last_path_segment(qpath).ident.name; - self.lints.push(sym_to_string(lint_name).to_ascii_lowercase()); - } else if let Some(local) = get_parent_local(self.cx, expr) { - if let Some(local_init) = local.init { - intravisit::walk_expr(self, local_init); - } - } - } - - intravisit::walk_expr(self, expr); - } -} - -/// This visitor finds the highest applicability value in the visited expressions -struct ApplicabilityResolver<'a, 'hir> { - cx: &'a LateContext<'hir>, - /// This is the index of highest `Applicability` for `paths::APPLICABILITY_VALUES` - applicability_index: Option<usize>, -} - -impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - applicability_index: None, - } - } - - fn add_new_index(&mut self, new_index: usize) { - self.applicability_index = take_higher_applicability(self.applicability_index, Some(new_index)); - } - - fn complete(self) -> Option<usize> { - self.applicability_index - } -} - -impl<'a, 'hir> Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_path(&mut self, path: &hir::Path<'hir>, _id: hir::HirId) { - for (index, enum_value) in paths::APPLICABILITY_VALUES.iter().enumerate() { - if match_path(path, enum_value) { - self.add_new_index(index); - return; - } - } - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr)); - - if match_type(self.cx, expr_ty, &paths::APPLICABILITY) - && let Some(local) = get_parent_local(self.cx, expr) - && let Some(local_init) = local.init - { - intravisit::walk_expr(self, local_init); - }; - - intravisit::walk_expr(self, expr); - } -} - -/// This returns the parent local node if the expression is a reference one -fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::LetStmt<'hir>> { - if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind { - if let hir::def::Res::Local(local_hir) = path.res { - return get_parent_local_hir_id(cx, local_hir); - } - } - - None -} - -fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::LetStmt<'hir>> { - match cx.tcx.parent_hir_node(hir_id) { - hir::Node::LetStmt(local) => Some(local), - hir::Node::Pat(pattern) => get_parent_local_hir_id(cx, pattern.hir_id), - _ => None, - } -} - -/// This visitor finds the highest applicability value in the visited expressions -struct IsMultiSpanScanner<'a, 'hir> { - cx: &'a LateContext<'hir>, - suggestion_count: usize, -} - -impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> { - fn new(cx: &'a LateContext<'hir>) -> Self { - Self { - cx, - suggestion_count: 0, - } - } - - /// Add a new single expression suggestion to the counter - fn add_single_span_suggestion(&mut self) { - self.suggestion_count += 1; - } - - /// Signals that a suggestion with possible multiple spans was found - fn add_multi_part_suggestion(&mut self) { - self.suggestion_count += 2; - } - - /// Checks if the suggestions include multiple spans - fn is_multi_part(&self) -> bool { - self.suggestion_count > 1 - } -} - -impl<'a, 'hir> Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.cx.tcx.hir() - } - - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { - // Early return if the lint is already multi span - if self.is_multi_part() { - return; - } - - if let ExprKind::MethodCall(path, recv, _, _arg_span) = &expr.kind { - let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv)); - if match_type(self.cx, self_ty, &paths::DIAG) { - let called_method = path.ident.name.as_str().to_string(); - for (method_name, is_multi_part) in &SUGGESTION_DIAG_METHODS { - if *method_name == called_method { - if *is_multi_part { - self.add_multi_part_suggestion(); - } else { - self.add_single_span_suggestion(); - } - break; - } - } - } - } - - intravisit::walk_expr(self, expr); - } -} diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 228db14d1b7..d3e49bff422 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -5,7 +5,7 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{get_parent_expr, higher, is_in_test, is_trait_method}; @@ -214,9 +214,11 @@ impl SuggestedType { } fn snippet(self, cx: &LateContext<'_>, args_span: Option<Span>, len_span: Option<Span>) -> String { - let maybe_args = args_span.and_then(|sp| snippet_opt(cx, sp)).unwrap_or_default(); + let maybe_args = args_span + .and_then(|sp| sp.get_source_text(cx)) + .map_or(String::new(), |x| x.to_owned()); let maybe_len = len_span - .and_then(|sp| snippet_opt(cx, sp).map(|s| format!("; {s}"))) + .and_then(|sp| sp.get_source_text(cx).map(|s| format!("; {s}"))) .unwrap_or_default(); match self { diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs index 63f3a5d7f83..7a85196ceca 100644 --- a/src/tools/clippy/clippy_lints/src/visibility.rs +++ b/src/tools/clippy/clippy_lints/src/visibility.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{Item, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; @@ -82,9 +82,7 @@ impl EarlyLintPass for Visibility { if !in_external_macro(cx.sess(), item.span) && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind { - if **path == kw::SelfLower - && let Some(false) = is_from_proc_macro(cx, item.vis.span) - { + if **path == kw::SelfLower && !is_from_proc_macro(cx, item.vis.span) { span_lint_and_then( cx, NEEDLESS_PUB_SELF, @@ -104,7 +102,7 @@ impl EarlyLintPass for Visibility { if (**path == kw::Super || **path == kw::SelfLower || **path == kw::Crate) && !*shorthand && let [.., last] = &*path.segments - && let Some(false) = is_from_proc_macro(cx, item.vis.span) + && !is_from_proc_macro(cx, item.vis.span) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( @@ -125,7 +123,7 @@ impl EarlyLintPass for Visibility { if *shorthand && let [.., last] = &*path.segments - && let Some(false) = is_from_proc_macro(cx, item.vis.span) + && !is_from_proc_macro(cx, item.vis.span) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( @@ -147,6 +145,6 @@ impl EarlyLintPass for Visibility { } } -fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> Option<bool> { - snippet_opt(cx, span).map(|s| !s.starts_with("pub")) +fn is_from_proc_macro(cx: &EarlyContext<'_>, span: Span) -> bool { + !span.check_source_text(cx, |src| src.starts_with("pub")) } diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index c4d64ee4609..7d9e58ad2f8 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -100,14 +100,14 @@ declare_clippy_lint! { pub struct WildcardImports { warn_on_all: bool, - allowed_segments: &'static FxHashSet<String>, + allowed_segments: FxHashSet<String>, } impl WildcardImports { pub fn new(conf: &'static Conf) -> Self { Self { warn_on_all: conf.warn_on_all_wildcard_imports, - allowed_segments: &conf.allowed_wildcard_imports, + allowed_segments: conf.allowed_wildcard_imports.iter().cloned().collect(), } } } @@ -181,7 +181,7 @@ impl WildcardImports { fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { item.span.from_expansion() || is_prelude_import(segments) - || is_allowed_via_config(segments, self.allowed_segments) + || is_allowed_via_config(segments, &self.allowed_segments) || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id())) } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 54e7e92f0c4..ec5a5896fb2 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::is_in_test; use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall}; -use clippy_utils::source::{expand_past_previous_comma, snippet_opt}; +use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt}; use rustc_ast::token::LitKind; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, @@ -397,7 +397,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call: &Ma format!("using `{name}!()` with a format string that ends in a single newline"), |diag| { let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!'); - let Some(format_snippet) = snippet_opt(cx, format_string_span) else { + let Some(format_snippet) = format_string_span.get_source_text(cx) else { return; }; @@ -492,7 +492,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { && let Some(arg) = format_args.arguments.by_index(index) && let rustc_ast::ExprKind::Lit(lit) = &arg.expr.kind && !arg.expr.span.from_expansion() - && let Some(value_string) = snippet_opt(cx, arg.expr.span) + && let Some(value_string) = arg.expr.span.get_source_text(cx) { let (replacement, replace_raw) = match lit.kind { LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) { @@ -515,7 +515,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { _ => continue, }; - let Some(format_string_snippet) = snippet_opt(cx, format_args.span) else { + let Some(format_string_snippet) = format_args.span.get_source_text(cx) else { continue; }; let format_string_is_raw = format_string_snippet.starts_with('r'); diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index 9fefd94d339..629ce9d04d4 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -8,7 +8,6 @@ publish = false clippy_config = { path = "../clippy_config" } arrayvec = { version = "0.7", default-features = false } itertools = "0.12" -rustc-semver = "1.1" # FIXME(f16_f128): remove when no longer needed for parsing rustc_apfloat = "0.2.0" diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index d2200bcf710..42c8b218d14 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -7,7 +7,7 @@ use rustc_session::Session; use rustc_span::{sym, Span}; use std::str::FromStr; -use crate::source::snippet_opt; +use crate::source::SpanRangeExt; use crate::tokenize_with_text; /// Deprecation status of attributes known by Clippy. @@ -179,25 +179,23 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { /// Checks if the given span contains a `#[cfg(..)]` attribute pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool { - let Some(snip) = snippet_opt(cx, s) else { - // Assume true. This would require either an invalid span, or one which crosses file boundaries. - return true; - }; - let mut iter = tokenize_with_text(&snip); + s.check_source_text(cx, |src| { + let mut iter = tokenize_with_text(src); - // Search for the token sequence [`#`, `[`, `cfg`] - while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { - let mut iter = iter.by_ref().skip_while(|(t, _)| { - matches!( - t, - TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } - ) - }); - if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) - && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) - { - return true; + // Search for the token sequence [`#`, `[`, `cfg`] + while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) { + let mut iter = iter.by_ref().skip_while(|(t, _)| { + matches!( + t, + TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } + ) + }); + if matches!(iter.next(), Some((TokenKind::OpenBracket, _))) + && matches!(iter.next(), Some((TokenKind::Ident, "cfg"))) + { + return true; + } } - } - false + false + }) } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 7f2234b310b..2bd6837d973 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -123,16 +123,14 @@ fn qpath_search_pat(path: &QPath<'_>) -> (Pat, Pat) { fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { let (head, tail) = match path.segments { - [head, .., tail] => (head, tail), - [p] => (p, p), [] => return (Pat::Str(""), Pat::Str("")), + [p] => (Pat::Sym(p.ident.name), p), + // QPath::Resolved can have a path that looks like `<Foo as Bar>::baz` where + // the path (`Bar::baz`) has it's span covering the whole QPath. + [.., tail] => (Pat::Str(""), tail), }; ( - if head.ident.name == kw::PathRoot { - Pat::Str("::") - } else { - Pat::Sym(head.ident.name) - }, + head, if tail.args.is_some() { Pat::Str(">") } else { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index e907e4058e5..760d5bc95f7 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -687,7 +687,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt) && let expr_lo = expr_span.lo() && expr_lo >= span.lo - && let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx) + && let Some(src) = (span.lo..expr_lo).get_source_range(&self.tcx) && let Some(src) = src.as_str() { use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace}; diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f325e4eaf15..f61ef9ac1b0 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1,6 +1,6 @@ use crate::consts::ConstEvalCtxt; use crate::macros::macro_backtrace; -use crate::source::{snippet_opt, walk_span_to_context, SpanRange, SpanRangeExt}; +use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt}; use crate::tokenize_with_text; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxHasher; @@ -588,10 +588,9 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' // block with an empty span. ([], None) if block.span.is_empty() => &ExprKind::Tup(&[]), // `{}` => `()` - ([], None) => match snippet_opt(cx, block.span) { - // Don't reduce if there are any tokens contained in the braces - Some(snip) - if tokenize(&snip) + ([], None) + if block.span.check_source_text(cx, |src| { + tokenize(src) .map(|t| t.kind) .filter(|t| { !matches!( @@ -599,11 +598,10 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace ) }) - .ne([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) => - { - kind - }, - _ => &ExprKind::Tup(&[]), + .eq([TokenKind::OpenBrace, TokenKind::CloseBrace].iter().copied()) + }) => + { + &ExprKind::Tup(&[]) }, ([], Some(expr)) => match expr.kind { // `{ return .. }` => `return ..` @@ -1191,9 +1189,9 @@ fn eq_span_tokens( pred: impl Fn(TokenKind) -> bool, ) -> bool { fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool { - if let Some(lsrc) = left.get_source_text(cx) + if let Some(lsrc) = left.get_source_range(cx) && let Some(lsrc) = lsrc.as_str() - && let Some(rsrc) = right.get_source_text(cx) + && let Some(rsrc) = right.get_source_range(cx) && let Some(rsrc) = rsrc.as_str() { let pred = |t: &(_, _)| pred(t.0); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 28755ae0710..5db14872c36 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -149,6 +149,7 @@ macro_rules! extract_msrv_attr { /// If the given expression is a local binding, find the initializer expression. /// If that initializer expression is another local binding, find its initializer again. +/// /// This process repeats as long as possible (but usually no more than once). Initializer /// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`] /// instead. @@ -179,6 +180,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr } /// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable. +/// /// By only considering immutable bindings, we guarantee that the returned expression represents the /// value of the binding wherever it is referenced. /// @@ -431,12 +433,12 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc }) } -/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the +/// THIS METHOD IS DEPRECATED. Matches a `QPath` against a slice of segment string literals. +/// +/// This method is deprecated and will eventually be removed since it does not match against the /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from /// `QPath::Resolved.1.res.opt_def_id()`. /// -/// Matches a `QPath` against a slice of segment string literals. -/// /// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a /// `rustc_hir::QPath`. /// @@ -485,12 +487,12 @@ pub fn is_path_diagnostic_item<'tcx>( path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id)) } -/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the +/// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals. +/// +/// This method is deprecated and will eventually be removed since it does not match against the /// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from /// `QPath::Resolved.1.res.opt_def_id()`. /// -/// Matches a `Path` against a slice of segment string literals. -/// /// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a /// `rustc_hir::Path`. /// @@ -905,6 +907,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> } /// Returns true if the expr is equal to `Default::default()` of it's type when evaluated. +/// /// It doesn't cover all cases, for example indirect function calls (some of std /// functions are supported) but it is the best we have. pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { @@ -1061,6 +1064,7 @@ impl std::ops::BitOrAssign for CaptureKind { } /// Given an expression referencing a local, determines how it would be captured in a closure. +/// /// Note as this will walk up to parent expressions until the capture can be determined it should /// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or /// function argument (other than a receiver). @@ -2365,8 +2369,9 @@ pub fn fn_def_id_with_node_args<'tcx>( } /// Returns `Option<String>` where String is a textual representation of the type encapsulated in -/// the slice iff the given expression is a slice of primitives (as defined in the -/// `is_recursively_primitive_type` function) and `None` otherwise. +/// the slice iff the given expression is a slice of primitives. +/// +/// (As defined in the `is_recursively_primitive_type` function.) Returns `None` otherwise. pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> { let expr_type = cx.typeck_results().expr_ty_adjusted(expr); let expr_kind = expr_type.kind(); diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index 455239cc37f..1d7479bff82 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -150,10 +150,11 @@ pub fn first_node_macro_backtrace(cx: &LateContext<'_>, node: &impl HirNode) -> } /// If `node` is the "first node" in a macro expansion, returns `Some` with the `ExpnId` of the -/// macro call site (i.e. the parent of the macro expansion). This generally means that `node` -/// is the outermost node of an entire macro expansion, but there are some caveats noted below. -/// This is useful for finding macro calls while visiting the HIR without processing the macro call -/// at every node within its expansion. +/// macro call site (i.e. the parent of the macro expansion). +/// +/// This generally means that `node` is the outermost node of an entire macro expansion, but there +/// are some caveats noted below. This is useful for finding macro calls while visiting the HIR +/// without processing the macro call at every node within its expansion. /// /// If you already have immediate access to the parent node, it is simpler to /// just check the context of that span directly (e.g. `parent.span.from_expansion()`). @@ -426,12 +427,8 @@ impl FormatArgsStorage { } } -/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if -/// it cannot be found it will return the [`rustc_ast::Expr`]. -pub fn find_format_arg_expr<'hir, 'ast>( - start: &'hir Expr<'hir>, - target: &'ast FormatArgument, -) -> Result<&'hir Expr<'hir>, &'ast rustc_ast::Expr> { +/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value +pub fn find_format_arg_expr<'hir>(start: &'hir Expr<'hir>, target: &FormatArgument) -> Option<&'hir Expr<'hir>> { let SpanData { lo, hi, @@ -449,7 +446,6 @@ pub fn find_format_arg_expr<'hir, 'ast>( ControlFlow::Continue(()) } }) - .ok_or(&target.expr) } /// Span of the `:` and format specifiers diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 95fbf0b2ea2..d9befb3c157 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -18,7 +18,6 @@ use rustc_middle::mir::{ use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt}; -use rustc_semver::RustcVersion; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext}; @@ -391,11 +390,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool { StableSince::Err => return false, }; - msrv.meets(RustcVersion::new( - u32::from(const_stab_rust_version.major), - u32::from(const_stab_rust_version.minor), - u32::from(const_stab_rust_version.patch), - )) + msrv.meets(const_stab_rust_version) } else { // Unstable const fn with the feature enabled. msrv.current().is_none() diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 96dd3c55d37..482e1e0147b 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -16,7 +16,7 @@ use rustc_span::{ }; use std::borrow::Cow; use std::fmt; -use std::ops::Range; +use std::ops::{Deref, Index, Range}; pub trait HasSession { fn sess(&self) -> &Session; @@ -94,10 +94,16 @@ impl IntoSpan for Range<BytePos> { } pub trait SpanRangeExt: SpanRange { + /// Attempts to get a handle to the source text. Returns `None` if either the span is malformed, + /// or the source text is not accessible. + fn get_source_text(self, cx: &impl HasSession) -> Option<SourceText> { + get_source_range(cx.sess().source_map(), self.into_range()).and_then(SourceText::new) + } + /// Gets the source file, and range in the file, of the given span. Returns `None` if the span /// extends through multiple files, or is malformed. - fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> { - get_source_text(cx.sess().source_map(), self.into_range()) + fn get_source_range(self, cx: &impl HasSession) -> Option<SourceFileRange> { + get_source_range(cx.sess().source_map(), self.into_range()) } /// Calls the given function with the source text referenced and returns the value. Returns @@ -144,32 +150,70 @@ pub trait SpanRangeExt: SpanRange { fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> { trim_start(cx.sess().source_map(), self.into_range()) } +} +impl<T: SpanRange> SpanRangeExt for T {} - /// Writes the referenced source text to the given writer. Will return `Err` if the source text - /// could not be retrieved. - fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result { - write_source_text_to(cx.sess().source_map(), self.into_range(), dst) +/// Handle to a range of text in a source file. +pub struct SourceText(SourceFileRange); +impl SourceText { + /// Takes ownership of the source file handle if the source text is accessible. + pub fn new(text: SourceFileRange) -> Option<Self> { + if text.as_str().is_some() { + Some(Self(text)) + } else { + None + } } - /// Extracts the referenced source text as an owned string. - fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> { - self.with_source_text(cx, ToOwned::to_owned) + /// Gets the source text. + pub fn as_str(&self) -> &str { + self.0.as_str().unwrap() + } + + /// Converts this into an owned string. + pub fn to_owned(&self) -> String { + self.as_str().to_owned() + } +} +impl Deref for SourceText { + type Target = str; + fn deref(&self) -> &Self::Target { + self.as_str() + } +} +impl AsRef<str> for SourceText { + fn as_ref(&self) -> &str { + self.as_str() + } +} +impl<T> Index<T> for SourceText +where + str: Index<T>, +{ + type Output = <str as Index<T>>::Output; + fn index(&self, idx: T) -> &Self::Output { + &self.as_str()[idx] + } +} +impl fmt::Display for SourceText { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) } } -impl<T: SpanRange> SpanRangeExt for T {} -fn get_source_text(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> { +fn get_source_range(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> { let start = sm.lookup_byte_offset(sp.start); let end = sm.lookup_byte_offset(sp.end); if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos { return None; } + sm.ensure_source_file_source_present(&start.sf); let range = start.pos.to_usize()..end.pos.to_usize(); Some(SourceFileRange { sf: start.sf, range }) } fn with_source_text<T>(sm: &SourceMap, sp: Range<BytePos>, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> { - if let Some(src) = get_source_text(sm, sp) + if let Some(src) = get_source_range(sm, sp) && let Some(src) = src.as_str() { Some(f(src)) @@ -183,7 +227,7 @@ fn with_source_text_and_range<T>( sp: Range<BytePos>, f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T, ) -> Option<T> { - if let Some(src) = get_source_text(sm, sp) + if let Some(src) = get_source_range(sm, sp) && let Some(text) = &src.sf.src { Some(f(text, src.range)) @@ -198,7 +242,7 @@ fn map_range( sp: Range<BytePos>, f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>, ) -> Option<Range<BytePos>> { - if let Some(src) = get_source_text(sm, sp.clone()) + if let Some(src) = get_source_range(sm, sp.clone()) && let Some(text) = &src.sf.src && let Some(range) = f(text, src.range.clone()) { @@ -232,13 +276,6 @@ fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> { .unwrap_or(sp) } -fn write_source_text_to(sm: &SourceMap, sp: Range<BytePos>, dst: &mut impl fmt::Write) -> fmt::Result { - match with_source_text(sm, sp, |src| dst.write_str(src)) { - Some(x) => x, - None => Err(fmt::Error), - } -} - pub struct SourceFileRange { pub sf: Lrc<SourceFile>, pub range: Range<usize>, @@ -247,7 +284,11 @@ impl SourceFileRange { /// Attempts to get the text from the source file. This can fail if the source text isn't /// loaded. pub fn as_str(&self) -> Option<&str> { - self.sf.src.as_ref().and_then(|x| x.get(self.range.clone())) + self.sf + .src + .as_ref() + .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source())) + .and_then(|x| x.get(self.range.clone())) } } @@ -548,9 +589,10 @@ pub fn snippet_block_with_context<'a>( (reindent_multiline(snip, true, indent), from_macro) } -/// Same as `snippet_with_applicability`, but first walks the span up to the given context. This -/// will result in the macro call, rather than the expansion, if the span is from a child context. -/// If the span is not from a child context, it will be used directly instead. +/// Same as `snippet_with_applicability`, but first walks the span up to the given context. +/// +/// This will result in the macro call, rather than the expansion, if the span is from a child +/// context. If the span is not from a child context, it will be used directly instead. /// /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR node /// would result in `box []`. If given the context of the address of expression, this function will @@ -593,9 +635,10 @@ fn snippet_with_context_sess<'a>( } /// Walks the span up to the target context, thereby returning the macro call site if the span is -/// inside a macro expansion, or the original span if it is not. Note this will return `None` in the -/// case of the span being in a macro expansion, but the target context is from expanding a macro -/// argument. +/// inside a macro expansion, or the original span if it is not. +/// +/// Note this will return `None` in the case of the span being in a macro expansion, but the target +/// context is from expanding a macro argument. /// /// Given the following /// diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2f6faba073e..f80981c11af 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -160,8 +160,10 @@ pub fn get_type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option<Symb } /// Returns true if `ty` is a type on which calling `Clone` through a function instead of -/// as a method, such as `Arc::clone()` is considered idiomatic. Lints should avoid suggesting to -/// replace instances of `ty::Clone()` by `.clone()` for objects of those types. +/// as a method, such as `Arc::clone()` is considered idiomatic. +/// +/// Lints should avoid suggesting to replace instances of `ty::Clone()` by `.clone()` for objects +/// of those types. pub fn should_call_clone_as_function(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { matches!( get_type_diagnostic_name(cx, ty), @@ -398,8 +400,10 @@ fn is_normalizable_helper<'tcx>( } /// Returns `true` if the given type is a non aggregate primitive (a `bool` or `char`, any -/// integer or floating-point number type). For checking aggregation of primitive types (e.g. -/// tuples and slices of primitive type) see `is_recursively_primitive_type` +/// integer or floating-point number type). +/// +/// For checking aggregation of primitive types (e.g. tuples and slices of primitive type) see +/// `is_recursively_primitive_type` pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool { matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_)) } @@ -455,11 +459,6 @@ pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: LangItem) } } -/// Gets the diagnostic name of the type, if it has one -pub fn type_diagnostic_name(cx: &LateContext<'_>, ty: Ty<'_>) -> Option<Symbol> { - ty.ty_adt_def().and_then(|adt| cx.tcx.get_diagnostic_name(adt.did())) -} - /// Return `true` if the passed `typ` is `isize` or `usize`. pub fn is_isize_or_usize(typ: Ty<'_>) -> bool { matches!(typ.kind(), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize)) @@ -476,9 +475,10 @@ pub fn match_type(cx: &LateContext<'_>, ty: Ty<'_>, path: &[&str]) -> bool { } } -/// Checks if the drop order for a type matters. Some std types implement drop solely to -/// deallocate memory. For these types, and composites containing them, changing the drop order -/// won't result in any observable side effects. +/// Checks if the drop order for a type matters. +/// +/// Some std types implement drop solely to deallocate memory. For these types, and composites +/// containing them, changing the drop order won't result in any observable side effects. pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet<Ty<'tcx>>) -> bool { if !seen.insert(ty) { @@ -1311,6 +1311,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl } /// Checks if a Ty<'_> has some inherent method Symbol. +/// /// This does not look for impls in the type's `Deref::Target` type. /// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`. pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> { diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs index ca070f6c250..6aa24329b06 100644 --- a/src/tools/clippy/declare_clippy_lint/src/lib.rs +++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(let_chains)] +#![feature(let_chains, proc_macro_span)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] @@ -23,6 +23,7 @@ fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) -> struct ClippyLint { attrs: Vec<Attribute>, + version: Option<LitStr>, explanation: String, name: Ident, category: Ident, @@ -41,8 +42,14 @@ impl Parse for ClippyLint { let value = lit.value(); let line = value.strip_prefix(' ').unwrap_or(&value); - if line.starts_with("```") { - explanation += "```\n"; + if let Some(lang) = line.strip_prefix("```") { + let tag = lang.split_once(',').map_or(lang, |(left, _)| left); + if !in_code && matches!(tag, "" | "rust" | "ignore" | "should_panic" | "no_run" | "compile_fail") { + explanation += "```rust\n"; + } else { + explanation += line; + explanation.push('\n'); + } in_code = !in_code; } else if !(in_code && line.starts_with("# ")) { explanation += line; @@ -68,6 +75,7 @@ impl Parse for ClippyLint { Ok(Self { attrs, + version, explanation, name, category, @@ -123,6 +131,7 @@ impl Parse for ClippyLint { pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { let ClippyLint { attrs, + version, explanation, name, category, @@ -146,6 +155,14 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { (&mut category[0..1]).make_ascii_uppercase(); let category_variant = format_ident!("{category}"); + let name_span = name.span().unwrap(); + let location = format!("{}#L{}", name_span.source_file().path().display(), name_span.line()); + + let version = match version { + Some(version) => quote!(Some(#version)), + None => quote!(None), + }; + let output = quote! { rustc_session::declare_tool_lint! { #(#attrs)* @@ -159,6 +176,8 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream { lint: &#name, category: crate::LintCategory::#category_variant, explanation: #explanation, + location: #location, + version: #version, }; }; diff --git a/src/tools/clippy/lintcheck/src/json.rs b/src/tools/clippy/lintcheck/src/json.rs index 4211bce90b2..ee0c80aea52 100644 --- a/src/tools/clippy/lintcheck/src/json.rs +++ b/src/tools/clippy/lintcheck/src/json.rs @@ -12,21 +12,21 @@ const TRUNCATION_TOTAL_TARGET: usize = 1000; #[derive(Debug, Deserialize, Serialize)] struct LintJson { - lint: String, - krate: String, - file_name: String, - byte_pos: (u32, u32), - file_link: String, + /// The lint name e.g. `clippy::bytes_nth` + name: String, + /// The filename and line number e.g. `anyhow-1.0.86/src/error.rs:42` + file_line: String, + file_url: String, rendered: String, } impl LintJson { fn key(&self) -> impl Ord + '_ { - (self.lint.as_str(), self.file_name.as_str(), self.byte_pos) + (self.name.as_str(), self.file_line.as_str()) } fn info_text(&self, action: &str) -> String { - format!("{action} `{}` in `{}` at {}", self.lint, self.krate, self.file_link) + format!("{action} `{}` at [`{}`]({})", self.name, self.file_line, self.file_url) } } @@ -36,13 +36,16 @@ pub(crate) fn output(clippy_warnings: Vec<ClippyWarning>) -> String { .into_iter() .map(|warning| { let span = warning.span(); + let file_name = span + .file_name + .strip_prefix("target/lintcheck/sources/") + .unwrap_or(&span.file_name); + let file_line = format!("{file_name}:{}", span.line_start); LintJson { - file_name: span.file_name.clone(), - byte_pos: (span.byte_start, span.byte_end), - krate: warning.krate, - file_link: warning.url, - lint: warning.lint, - rendered: warning.diag.rendered.unwrap(), + name: warning.name, + file_line, + file_url: warning.url, + rendered: warning.diag.rendered.unwrap().trim().to_string(), } }) .collect(); @@ -63,7 +66,7 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { let mut lint_warnings = vec![]; for (name, changes) in &itertools::merge_join_by(old_warnings, new_warnings, |old, new| old.key().cmp(&new.key())) - .chunk_by(|change| change.as_ref().into_left().lint.to_string()) + .chunk_by(|change| change.as_ref().into_left().name.clone()) { let mut added = Vec::new(); let mut removed = Vec::new(); @@ -162,7 +165,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { return; } - print_h3(&warnings[0].lint, title); + print_h3(&warnings[0].name, title); println!(); let warnings = truncate(warnings, truncate_after); @@ -171,7 +174,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { println!("{}", warning.info_text(title)); println!(); println!("```"); - println!("{}", warning.rendered.trim_end()); + println!("{}", warning.rendered); println!("```"); println!(); } @@ -182,7 +185,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { return; } - print_h3(&changed[0].0.lint, "Changed"); + print_h3(&changed[0].0.name, "Changed"); println!(); let changed = truncate(changed, truncate_after); @@ -191,7 +194,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { println!("{}", new.info_text("Changed")); println!(); println!("```diff"); - for change in diff::lines(old.rendered.trim_end(), new.rendered.trim_end()) { + for change in diff::lines(&old.rendered, &new.rendered) { use diff::Result::{Both, Left, Right}; match change { diff --git a/src/tools/clippy/lintcheck/src/output.rs b/src/tools/clippy/lintcheck/src/output.rs index 15378630695..e38036315c2 100644 --- a/src/tools/clippy/lintcheck/src/output.rs +++ b/src/tools/clippy/lintcheck/src/output.rs @@ -51,7 +51,7 @@ impl RustcIce { /// A single warning that clippy issued while checking a `Crate` #[derive(Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ClippyWarning { - pub lint: String, + pub name: String, pub diag: Diagnostic, pub krate: String, /// The URL that points to the file and line of the lint emission @@ -60,8 +60,8 @@ pub struct ClippyWarning { impl ClippyWarning { pub fn new(mut diag: Diagnostic, base_url: &str, krate: &str) -> Option<Self> { - let lint = diag.code.clone()?.code; - if !(lint.contains("clippy") || diag.message.contains("clippy")) + let name = diag.code.clone()?.code; + if !(name.contains("clippy") || diag.message.contains("clippy")) || diag.message.contains("could not read cargo metadata") { return None; @@ -92,7 +92,7 @@ impl ClippyWarning { }; Some(Self { - lint, + name, diag, url, krate: krate.to_string(), @@ -108,7 +108,7 @@ impl ClippyWarning { let mut file = span.file_name.clone(); let file_with_pos = format!("{file}:{}:{}", span.line_start, span.line_end); match format { - OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.lint, self.diag.message), + OutputFormat::Text => format!("{file_with_pos} {} \"{}\"\n", self.name, self.diag.message), OutputFormat::Markdown => { if file.starts_with("target") { file.insert_str(0, "../"); @@ -116,7 +116,7 @@ impl ClippyWarning { let mut output = String::from("| "); write!(output, "[`{file_with_pos}`]({file}#L{})", span.line_start).unwrap(); - write!(output, r#" | `{:<50}` | "{}" |"#, self.lint, self.diag.message).unwrap(); + write!(output, r#" | `{:<50}` | "{}" |"#, self.name, self.diag.message).unwrap(); output.push('\n'); output }, @@ -164,7 +164,7 @@ fn gather_stats(warnings: &[ClippyWarning]) -> (String, HashMap<&String, usize>) let mut counter: HashMap<&String, usize> = HashMap::new(); warnings .iter() - .for_each(|wrn| *counter.entry(&wrn.lint).or_insert(0) += 1); + .for_each(|wrn| *counter.entry(&wrn.name).or_insert(0) += 1); // collect into a tupled list for sorting let mut stats: Vec<(&&String, &usize)> = counter.iter().collect(); diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 5fbe4e544a9..0be2e81810e 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-08" +channel = "nightly-2024-08-23" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index 64253514fbe..9754254cdd0 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -1,25 +1,31 @@ -// We need this feature as it changes `dylib` linking behavior and allows us to link to -// `rustc_driver`. -#![feature(rustc_private)] +#![feature(rustc_private, let_chains)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unused_extern_crates)] +use cargo_metadata::diagnostic::{Applicability, Diagnostic}; +use cargo_metadata::Message; +use clippy_config::ClippyConfiguration; +use clippy_lints::declared_lints::LINTS; +use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use clippy_lints::LintInfo; +use serde::{Deserialize, Serialize}; +use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::rustfix::RustfixMode; +use ui_test::custom_flags::Flag; use ui_test::spanned::Spanned; +use ui_test::test_result::TestRun; use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::env::{self, set_var, var_os}; use std::ffi::{OsStr, OsString}; -use std::fs; +use std::fmt::Write; use std::path::{Path, PathBuf}; -use std::sync::LazyLock; -use test_utils::IS_RUSTC_TEST_SUITE; +use std::sync::mpsc::{channel, Sender}; +use std::{fs, iter, thread}; // Test dependencies may need an `extern crate` here to ensure that they show up // in the depinfo file (otherwise cargo thinks they are unused) -extern crate clippy_lints; -extern crate clippy_utils; extern crate futures; extern crate if_chain; extern crate itertools; @@ -55,7 +61,7 @@ static TEST_DEPENDENCIES: &[&str] = &[ /// dependencies must be added to Cargo.toml at the project root. Test /// dependencies that are not *directly* used by this test module require an /// `extern crate` declaration. -static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| { +fn extern_flags() -> Vec<String> { let current_exe_depinfo = { let mut path = env::current_exe().unwrap(); path.set_extension("d"); @@ -103,70 +109,93 @@ static EXTERN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| { .into_iter() .map(|(name, path)| format!("--extern={name}={path}")) .collect() -}); +} // whether to run internal tests or not const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); -fn base_config(test_dir: &str) -> (Config, Args) { - let mut args = Args::test().unwrap(); - args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); - - let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); - let mut config = Config { - output_conflict_handling: OutputConflictHandling::Error, - filter_files: env::var("TESTNAME") - .map(|filters| filters.split(',').map(str::to_string).collect()) - .unwrap_or_default(), - target: None, - bless_command: Some("cargo uibless".into()), - out_dir: target_dir.join("ui_test"), - ..Config::rustc(Path::new("tests").join(test_dir)) - }; - config.comment_defaults.base().exit_status = None.into(); - config.comment_defaults.base().require_annotations = None.into(); - config - .comment_defaults - .base() - .set_custom("rustfix", RustfixMode::Everything); - config.comment_defaults.base().diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); - config.with_args(&args); - let current_exe_path = env::current_exe().unwrap(); - let deps_path = current_exe_path.parent().unwrap(); - let profile_path = deps_path.parent().unwrap(); - - config.program.args.extend( - [ - "--emit=metadata", - "-Aunused", - "-Ainternal_features", - "-Zui-testing", - "-Zdeduplicate-diagnostics=no", - "-Dwarnings", - &format!("-Ldependency={}", deps_path.display()), - ] - .map(OsString::from), - ); - - config.program.args.extend(EXTERN_FLAGS.iter().map(OsString::from)); - // Prevent rustc from creating `rustc-ice-*` files the console output is enough. - config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); +struct TestContext { + args: Args, + extern_flags: Vec<String>, + diagnostic_collector: Option<DiagnosticCollector>, + collector_thread: Option<thread::JoinHandle<()>>, +} - if let Some(host_libs) = option_env!("HOST_LIBS") { - let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); - config.program.args.push(dep.into()); +impl TestContext { + fn new() -> Self { + let mut args = Args::test().unwrap(); + args.bless |= var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); + let (diagnostic_collector, collector_thread) = var_os("COLLECT_METADATA") + .is_some() + .then(DiagnosticCollector::spawn) + .unzip(); + Self { + args, + extern_flags: extern_flags(), + diagnostic_collector, + collector_thread, + } } - config.program.program = profile_path.join(if cfg!(windows) { - "clippy-driver.exe" - } else { - "clippy-driver" - }); - (config, args) + fn base_config(&self, test_dir: &str) -> Config { + let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); + let mut config = Config { + output_conflict_handling: OutputConflictHandling::Error, + filter_files: env::var("TESTNAME") + .map(|filters| filters.split(',').map(str::to_string).collect()) + .unwrap_or_default(), + target: None, + bless_command: Some("cargo uibless".into()), + out_dir: target_dir.join("ui_test"), + ..Config::rustc(Path::new("tests").join(test_dir)) + }; + let defaults = config.comment_defaults.base(); + defaults.exit_status = None.into(); + defaults.require_annotations = None.into(); + defaults.diagnostic_code_prefix = Some(Spanned::dummy("clippy::".into())).into(); + defaults.set_custom("rustfix", RustfixMode::Everything); + if let Some(collector) = self.diagnostic_collector.clone() { + defaults.set_custom("diagnostic-collector", collector); + } + config.with_args(&self.args); + let current_exe_path = env::current_exe().unwrap(); + let deps_path = current_exe_path.parent().unwrap(); + let profile_path = deps_path.parent().unwrap(); + + config.program.args.extend( + [ + "--emit=metadata", + "-Aunused", + "-Ainternal_features", + "-Zui-testing", + "-Zdeduplicate-diagnostics=no", + "-Dwarnings", + &format!("-Ldependency={}", deps_path.display()), + ] + .map(OsString::from), + ); + + config.program.args.extend(self.extern_flags.iter().map(OsString::from)); + // Prevent rustc from creating `rustc-ice-*` files the console output is enough. + config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); + + if let Some(host_libs) = option_env!("HOST_LIBS") { + let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); + config.program.args.push(dep.into()); + } + + config.program.program = profile_path.join(if cfg!(windows) { + "clippy-driver.exe" + } else { + "clippy-driver" + }); + + config + } } -fn run_ui() { - let (mut config, args) = base_config("ui"); +fn run_ui(cx: &TestContext) { + let mut config = cx.base_config("ui"); config .program .envs @@ -176,30 +205,29 @@ fn run_ui() { vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } -fn run_internal_tests() { - // only run internal tests with the internal-tests feature +fn run_internal_tests(cx: &TestContext) { if !RUN_INTERNAL_TESTS { return; } - let (mut config, args) = base_config("ui-internal"); + let mut config = cx.base_config("ui-internal"); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } -fn run_ui_toml() { - let (mut config, args) = base_config("ui-toml"); +fn run_ui_toml(cx: &TestContext) { + let mut config = cx.base_config("ui-toml"); config .comment_defaults @@ -217,19 +245,19 @@ fn run_ui_toml() { .envs .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into()))); }, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } // Allow `Default::default` as `OptWithSpan` is not nameable #[allow(clippy::default_trait_access)] -fn run_ui_cargo() { +fn run_ui_cargo(cx: &TestContext) { if IS_RUSTC_TEST_SUITE { return; } - let (mut config, args) = base_config("ui-cargo"); + let mut config = cx.base_config("ui-cargo"); config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; @@ -264,23 +292,25 @@ fn run_ui_cargo() { .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)) }, |_config, _file_contents| {}, - status_emitter::Text::from(args.format), + status_emitter::Text::from(cx.args.format), ) .unwrap(); } fn main() { set_var("CLIPPY_DISABLE_DOCS_LINKS", "true"); + + let cx = TestContext::new(); + // The SPEEDTEST_* env variables can be used to check Clippy's performance on your PR. It runs the // affected test 1000 times and gets the average. if let Ok(speedtest) = std::env::var("SPEEDTEST") { println!("----------- STARTING SPEEDTEST -----------"); let f = match speedtest.as_str() { - "ui" => run_ui as fn(), - "cargo" => run_ui_cargo as fn(), - "toml" => run_ui_toml as fn(), - "internal" => run_internal_tests as fn(), - "ui-cargo-toml-metadata" => ui_cargo_toml_metadata as fn(), + "ui" => run_ui, + "cargo" => run_ui_cargo, + "toml" => run_ui_toml, + "internal" => run_internal_tests, _ => panic!("unknown speedtest: {speedtest} || accepted speedtests are: [ui, cargo, toml, internal]"), }; @@ -297,7 +327,7 @@ fn main() { let mut sum = 0; for _ in 0..iterations { let start = std::time::Instant::now(); - f(); + f(&cx); sum += start.elapsed().as_millis(); } println!( @@ -306,11 +336,17 @@ fn main() { sum / u128::from(iterations) ); } else { - run_ui(); - run_ui_toml(); - run_ui_cargo(); - run_internal_tests(); + run_ui(&cx); + run_ui_toml(&cx); + run_ui_cargo(&cx); + run_internal_tests(&cx); + drop(cx.diagnostic_collector); + ui_cargo_toml_metadata(); + + if let Some(thread) = cx.collector_thread { + thread.join().unwrap(); + } } } @@ -349,3 +385,180 @@ fn ui_cargo_toml_metadata() { ); } } + +#[derive(Deserialize)] +#[serde(untagged)] +enum DiagnosticOrMessage { + Diagnostic(Diagnostic), + Message(Message), +} + +/// Collects applicabilities from the diagnostics produced for each UI test, producing the +/// `util/gh-pages/lints.json` file used by <https://rust-lang.github.io/rust-clippy/> +#[derive(Debug, Clone)] +struct DiagnosticCollector { + sender: Sender<Vec<u8>>, +} + +impl DiagnosticCollector { + #[allow(clippy::assertions_on_constants)] + fn spawn() -> (Self, thread::JoinHandle<()>) { + assert!(!IS_RUSTC_TEST_SUITE && !RUN_INTERNAL_TESTS); + + let (sender, receiver) = channel::<Vec<u8>>(); + + let handle = thread::spawn(|| { + let mut applicabilities = HashMap::new(); + + for stderr in receiver { + for line in stderr.split(|&byte| byte == b'\n') { + let diag = match serde_json::from_slice(line) { + Ok(DiagnosticOrMessage::Diagnostic(diag)) => diag, + Ok(DiagnosticOrMessage::Message(Message::CompilerMessage(message))) => message.message, + _ => continue, + }; + + if let Some(lint) = diag.code.as_ref().and_then(|code| code.code.strip_prefix("clippy::")) { + let applicability = applicabilities + .entry(lint.to_string()) + .or_insert(Applicability::Unspecified); + let diag_applicability = diag + .children + .iter() + .flat_map(|child| &child.spans) + .filter_map(|span| span.suggestion_applicability.clone()) + .max_by_key(applicability_ord); + if let Some(diag_applicability) = diag_applicability + && applicability_ord(&diag_applicability) > applicability_ord(applicability) + { + *applicability = diag_applicability; + } + } + } + } + + let configs = clippy_config::get_configuration_metadata(); + let mut metadata: Vec<LintMetadata> = LINTS + .iter() + .map(|lint| LintMetadata::new(lint, &applicabilities, &configs)) + .chain( + iter::zip(DEPRECATED, DEPRECATED_VERSION) + .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), + ) + .collect(); + metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); + + let json = serde_json::to_string_pretty(&metadata).unwrap(); + fs::write("util/gh-pages/lints.json", json).unwrap(); + }); + + (Self { sender }, handle) + } +} + +fn applicability_ord(applicability: &Applicability) -> u8 { + match applicability { + Applicability::MachineApplicable => 4, + Applicability::HasPlaceholders => 3, + Applicability::MaybeIncorrect => 2, + Applicability::Unspecified => 1, + _ => unimplemented!(), + } +} + +impl Flag for DiagnosticCollector { + fn post_test_action( + &self, + _config: &ui_test::per_test_config::TestConfig<'_>, + _cmd: &mut std::process::Command, + output: &std::process::Output, + _build_manager: &ui_test::build_manager::BuildManager<'_>, + ) -> Result<Vec<TestRun>, ui_test::Errored> { + if !output.stderr.is_empty() { + self.sender.send(output.stderr.clone()).unwrap(); + } + Ok(Vec::new()) + } + + fn clone_inner(&self) -> Box<dyn Flag> { + Box::new(self.clone()) + } + + fn must_be_unique(&self) -> bool { + true + } +} + +#[derive(Debug, Serialize)] +struct LintMetadata { + id: String, + id_location: Option<&'static str>, + group: &'static str, + level: &'static str, + docs: String, + version: &'static str, + applicability: Applicability, +} + +impl LintMetadata { + fn new(lint: &LintInfo, applicabilities: &HashMap<String, Applicability>, configs: &[ClippyConfiguration]) -> Self { + let name = lint.name_lower(); + let applicability = applicabilities + .get(&name) + .cloned() + .unwrap_or(Applicability::Unspecified); + let past_names = RENAMED + .iter() + .filter(|(_, new_name)| new_name.strip_prefix("clippy::") == Some(&name)) + .map(|(old_name, _)| old_name.strip_prefix("clippy::").unwrap()) + .collect::<Vec<_>>(); + let mut docs = lint.explanation.to_string(); + if !past_names.is_empty() { + docs.push_str("\n### Past names\n\n"); + for past_name in past_names { + writeln!(&mut docs, " * {past_name}").unwrap(); + } + } + let configs: Vec<_> = configs + .iter() + .filter(|conf| conf.lints.contains(&name.as_str())) + .collect(); + if !configs.is_empty() { + docs.push_str("\n### Configuration\n\n"); + for config in configs { + writeln!(&mut docs, "{config}").unwrap(); + } + } + Self { + id: name, + id_location: Some(lint.location), + group: lint.category_str(), + level: lint.lint.default_level.as_str(), + docs, + version: lint.version.unwrap(), + applicability, + } + } + + fn new_deprecated(name: &str, reason: &str, version: &'static str) -> Self { + // The reason starts with a lowercase letter and ends without a period. + // This needs to be fixed for the website. + let mut reason = reason.to_owned(); + if let Some(reason) = reason.get_mut(0..1) { + reason.make_ascii_uppercase(); + } + Self { + id: name.strip_prefix("clippy::").unwrap().into(), + id_location: None, + group: "deprecated", + level: "none", + version, + docs: format!( + "### What it does\n\n\ + Nothing. This lint has been deprecated\n\n\ + ### Deprecation reason\n\n{reason}.\n", + ), + applicability: Applicability::Unspecified, + } + } +} diff --git a/src/tools/clippy/tests/config-metadata.rs b/src/tools/clippy/tests/config-metadata.rs new file mode 100644 index 00000000000..3e3711873ba --- /dev/null +++ b/src/tools/clippy/tests/config-metadata.rs @@ -0,0 +1,78 @@ +#![feature(rustc_private)] + +use clippy_config::{get_configuration_metadata, ClippyConfiguration}; +use itertools::Itertools; +use regex::Regex; +use std::borrow::Cow; +use std::{env, fs}; + +fn metadata() -> impl Iterator<Item = ClippyConfiguration> { + get_configuration_metadata() + .into_iter() + .filter(|config| config.deprecation_reason.is_none()) + .filter(|config| !config.lints.is_empty()) +} + +#[test] +fn book() { + let path = "book/src/lint_configuration.md"; + let current = fs::read_to_string(path).unwrap(); + + let configs = metadata().map(|conf| conf.to_markdown_paragraph()).join("\n"); + let expected = format!( + r#"<!-- +This file is generated by `cargo bless --test config-metadata`. +Please use that command to update the file and do not edit it by hand. +--> + +# Lint Configuration Options + +The following list shows each configuration option, along with a description, its default value, an example +and lints affected. + +--- + +{} +"#, + configs.trim(), + ); + + if current != expected { + if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") { + fs::write(path, expected).unwrap(); + } else { + panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it"); + } + } +} + +#[test] +fn changelog() { + let path = "CHANGELOG.md"; + let current = fs::read_to_string(path).unwrap(); + + let configs = metadata().map(|conf| conf.to_markdown_link()).join("\n"); + + let re = Regex::new( + "(?s)\ + (<!-- begin autogenerated links to configuration documentation -->)\ + .*\ + (<!-- end autogenerated links to configuration documentation -->)\ + ", + ) + .unwrap(); + let expected = re.replace(¤t, format!("$1\n{configs}\n$2")); + + assert!( + matches!(expected, Cow::Owned(_)), + "failed to find configuration section in `{path}`" + ); + + if current != expected { + if env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0") { + fs::write(path, expected.as_bytes()).unwrap(); + } else { + panic!("`{path}` is out of date, run `cargo bless --test config-metadata` to update it"); + } + } +} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr index 1cc1034cd89..d24b0cd6162 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_crates.stderr @@ -1,29 +1,44 @@ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 | -LL | std::f32::MAX; - | ^^^^^^^^^^^^^ +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D clippy::absolute-paths` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]` +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 + | +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 | -LL | core::f32::MAX; - | ^^^^^^^^^^^^^^ +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 | -LL | ::core::f32::MAX; - | ^^^^^^^^^^^^^^^^ +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5 + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 | -LL | ::std::f32::MAX; - | ^^^^^^^^^^^^^^^ +LL | let _ = std::option::Option::None::<i32>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr new file mode 100644 index 00000000000..0cc6566af3a --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.allow_long.stderr @@ -0,0 +1,14 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr new file mode 100644 index 00000000000..53aa9030e0d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.default.stderr @@ -0,0 +1,80 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 + | +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 + | +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13 + | +LL | let _ = ::core::clone::Clone::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13 + | +LL | let _ = <i32 as core::clone::Clone>::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 + | +LL | let _ = std::option::Option::None::<i32>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17 + | +LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T> + | ^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18 + | +LL | where T: core::clone::Clone + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32 + | +LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T> + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5 + | +LL | crate::m1::S + | ^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr deleted file mode 100644 index f342ebf6632..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.disallow_crates.stderr +++ /dev/null @@ -1,71 +0,0 @@ -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:5 - | -LL | std::f32::MAX; - | ^^^^^^^^^^^^^ - | - = note: `-D clippy::absolute-paths` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::absolute_paths)]` - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:41:5 - | -LL | core::f32::MAX; - | ^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:42:5 - | -LL | ::core::f32::MAX; - | ^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:5 - | -LL | crate::a::b::c::C; - | ^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:44:5 - | -LL | crate::a::b::c::d::e::f::F; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:45:5 - | -LL | crate::a::A; - | ^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:46:5 - | -LL | crate::a::b::B; - | ^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:47:5 - | -LL | crate::a::b::c::C::ZERO; - | ^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:48:5 - | -LL | helper::b::c::d::e::f(); - | ^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:49:5 - | -LL | ::helper::b::c::d::e::f(); - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: consider bringing this path into scope with the `use` keyword - --> tests/ui-toml/absolute_paths/absolute_paths.rs:58:5 - | -LL | ::std::f32::MAX; - | ^^^^^^^^^^^^^^^ - -error: aborting due to 11 previous errors - diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr new file mode 100644 index 00000000000..70d71f6c4ea --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.no_short.stderr @@ -0,0 +1,98 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:14:13 + | +LL | let _ = std::path::is_separator(' '); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths.rs:7:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:20:13 + | +LL | let _ = ::std::path::MAIN_SEPARATOR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:25:13 + | +LL | let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:31 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:28:13 + | +LL | let _: &std::path::Path = std::path::Path::new(""); + | ^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:37:13 + | +LL | let _ = ::core::clone::Clone::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:40:13 + | +LL | let _ = <i32 as core::clone::Clone>::clone(&0i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:43:13 + | +LL | let _ = std::option::Option::None::<i32>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:17 + | +LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T> + | ^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:70:18 + | +LL | where T: core::clone::Clone + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:65:32 + | +LL | impl<T: core::cmp::Eq> core::fmt::Display for X<T> + | ^^^^^^^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:113:14 + | +LL | pub const _: crate::S = { + | ^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:114:9 + | +LL | let crate::S = m1::S; + | ^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:116:5 + | +LL | crate::m1::S + | ^^^^^^^^^^^^ + +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths.rs:122:14 + | +LL | let _ = <crate::S as Clone>::clone(&m1::S); + | ^^^^^^^^ + +error: aborting due to 15 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs index a828701bcee..c024f2f513c 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths.rs @@ -1,97 +1,123 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@aux-build:helper.rs -//@revisions: allow_crates disallow_crates +//@revisions: default allow_crates allow_long no_short +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default //@[allow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates -//@[disallow_crates] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/disallow_crates -#![allow(clippy::no_effect, clippy::legacy_numeric_constants, unused)] -#![warn(clippy::absolute_paths)] -#![feature(decl_macro)] +//@[allow_long] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_long +//@[no_short] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/no_short +#![deny(clippy::absolute_paths)] -extern crate helper; -#[macro_use] extern crate proc_macros; +use proc_macros::{external, inline_macros, with_span}; -pub mod a { - pub mod b { - pub mod c { - pub struct C; +#[inline_macros] +fn main() { + let _ = std::path::is_separator(' '); + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths - impl C { - pub const ZERO: u32 = 0; - } + // Make sure this is treated as having three path segments, not four. + let _ = ::std::path::MAIN_SEPARATOR; + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths - pub mod d { - pub mod e { - pub mod f { - pub struct F; - } - } - } - } + let _ = std::collections::hash_map::HashMap::<i32, i32>::new(); //~ absolute_paths - pub struct B; - } + // Note `std::path::Path::new` is treated as having three parts + let _: &std::path::Path = std::path::Path::new(""); + //~[default]^ absolute_paths + //~[default]| absolute_paths + //~[allow_crates]| absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths + //~[no_short]| absolute_paths - pub struct A; -} + // Treated as having three parts. + let _ = ::core::clone::Clone::clone(&0i32); + //~[default]^ absolute_paths + //~[no_short]| absolute_paths + let _ = <i32 as core::clone::Clone>::clone(&0i32); + //~[default]^ absolute_paths + //~[no_short]| absolute_paths + let _ = std::option::Option::None::<i32>; + //~[default]^ absolute_paths + //~[allow_crates]| absolute_paths + //~[no_short]| absolute_paths -fn main() { - f32::max(1.0, 2.0); - std::f32::MAX; - core::f32::MAX; - ::core::f32::MAX; - crate::a::b::c::C; - crate::a::b::c::d::e::f::F; - crate::a::A; - crate::a::b::B; - crate::a::b::c::C::ZERO; - helper::b::c::d::e::f(); - ::helper::b::c::d::e::f(); - fn b() -> a::b::B { - todo!() + { + // FIXME: macro calls should be checked. + let x = 1i32; + let _ = core::ptr::addr_of!(x); } - std::println!("a"); - let x = 1; - std::ptr::addr_of!(x); - // Test we handle max segments with `PathRoot` properly; this has 4 segments but we should say it - // has 3 - ::std::f32::MAX; - // Do not lint due to the above - ::helper::a(); - // Do not lint - helper::a(); - use crate::a::b::c::C; - use a::b; - use std::f32::MAX; - a::b::c::d::e::f::F; - b::c::C; - fn a() -> a::A { - todo!() - } - use a::b::c; - fn c() -> c::C { - todo!() + { + // FIXME: derive macro paths should be checked. + #[derive(core::clone::Clone)] + struct S; } - fn d() -> Result<(), ()> { - todo!() + + { + use core::fmt; + use core::marker::PhantomData; + + struct X<T>(PhantomData<T>); + impl<T: core::cmp::Eq> core::fmt::Display for X<T> + //~[default]^ absolute_paths + //~[default]| absolute_paths + //~[no_short]| absolute_paths + //~[no_short]| absolute_paths + where T: core::clone::Clone + //~[no_short]^ absolute_paths + //~[default]| absolute_paths + { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } + } } - external! { - crate::a::b::c::C::ZERO; + + { + mod m1 { + pub(crate) mod m2 { + pub(crate) const FOO: i32 = 0; + } + } + let _ = m1::m2::FOO; } - // For some reason, `path.span.from_expansion()` takes care of this for us + with_span! { span - crate::a::b::c::C::ZERO; + let _ = std::path::is_separator(' '); } - macro_rules! local_crate { - () => { - crate::a::b::c::C::ZERO; - }; + + external! { + let _ = std::path::is_separator(' '); } - macro local_crate_2_0() { - crate::a::b::c::C::ZERO; + + inline! { + let _ = std::path::is_separator(' '); } - local_crate!(); - local_crate_2_0!(); +} + +pub use core::cmp::Ordering; +pub use std::fs::File; + +#[derive(Clone)] +pub struct S; +mod m1 { + pub use crate::S; +} + +//~[no_short]v absolute_paths +pub const _: crate::S = { + let crate::S = m1::S; //~[no_short] absolute_paths + + crate::m1::S + //~[default]^ absolute_paths + //~[no_short]| absolute_paths +}; + +pub fn f() { + let _ = <crate::S as Clone>::clone(&m1::S); //~[no_short] absolute_paths } diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr new file mode 100644 index 00000000000..6fc495f0180 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.default.stderr @@ -0,0 +1,14 @@ +error: consider bringing this path into scope with the `use` keyword + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:15:13 + | +LL | let _ = ::m1::m2::X; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-toml/absolute_paths/absolute_paths_2015.rs:6:9 + | +LL | #![deny(clippy::absolute_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs new file mode 100644 index 00000000000..033c4780919 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/absolute_paths_2015.rs @@ -0,0 +1,16 @@ +//@revisions: default allow_crates +//@[default]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/default +//@[allow_crates]rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/absolute_paths/allow_crates +//@edition:2015 + +#![deny(clippy::absolute_paths)] + +mod m1 { + pub mod m2 { + pub struct X; + } +} + +fn main() { + let _ = ::m1::m2::X; //~[default] absolute_paths +} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml index 59a621e9d1d..9da49abcd31 100644 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_crates/clippy.toml @@ -1,2 +1 @@ -absolute-paths-max-segments = 2 -absolute-paths-allowed-crates = ["crate", "helper"] +absolute-paths-allowed-crates = ["core", "crate"] diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml new file mode 100644 index 00000000000..5992fd1ed82 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/allow_long/clippy.toml @@ -0,0 +1 @@ +absolute-paths-max-segments = 3 diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs b/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs deleted file mode 100644 index 8e2678f5fe6..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/auxiliary/helper.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub fn a() {} - -pub mod b { - pub mod c { - pub mod d { - pub mod e { - pub fn f() {} - } - } - } -} diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/default/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/default/clippy.toml new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/default/clippy.toml diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml deleted file mode 100644 index d44d648c641..00000000000 --- a/src/tools/clippy/tests/ui-toml/absolute_paths/disallow_crates/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -absolute-paths-max-segments = 2 diff --git a/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml b/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml new file mode 100644 index 00000000000..357524420c5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/absolute_paths/no_short/clippy.toml @@ -0,0 +1 @@ +absolute-paths-max-segments = 0 diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs index a312df5a43a..3dafea56514 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -1,7 +1,7 @@ //! Tests macro_metavars_in_unsafe with default configuration #![feature(decl_macro)] #![warn(clippy::macro_metavars_in_unsafe)] -#![allow(clippy::no_effect)] +#![allow(clippy::no_effect, clippy::not_unsafe_ptr_arg_deref)] #[macro_export] macro_rules! allow_works { @@ -237,6 +237,19 @@ macro_rules! nested_macros { }}; } +pub mod issue13219 { + #[macro_export] + macro_rules! m { + ($e:expr) => { + // Metavariable in a block tail expression + unsafe { $e } + }; + } + pub fn f(p: *const i32) -> i32 { + m!(*p) + } +} + fn main() { allow_works!(1); simple!(1); diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr index d6b97f6fde1..6f0ebcbba02 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr @@ -1,4 +1,16 @@ error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:245:13 + | +LL | unsafe { $e } + | ^^^^^^^^^^^^^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` + +error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9 | LL | / unsafe { @@ -10,8 +22,6 @@ LL | | } = note: this allows the user of the macro to write unsafe code outside of an unsafe block = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite - = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9 @@ -183,5 +193,5 @@ LL | | } = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed index b376d55a402..09732d1a50c 100644 --- a/src/tools/clippy/tests/ui/assigning_clones.fixed +++ b/src/tools/clippy/tests/ui/assigning_clones.fixed @@ -396,3 +396,23 @@ impl<T: Clone> Clone for DerefWrapperWithClone<T> { *self = Self(source.0.clone()); } } + +#[cfg(test)] +mod test { + #[derive(Default)] + struct Data { + field: String, + } + + fn test_data() -> Data { + Data { + field: "default_value".to_string(), + } + } + + #[test] + fn test() { + let mut data = test_data(); + data.field = "override_value".to_owned(); + } +} diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs index 11a5d4459c3..6be25ae17a5 100644 --- a/src/tools/clippy/tests/ui/assigning_clones.rs +++ b/src/tools/clippy/tests/ui/assigning_clones.rs @@ -396,3 +396,23 @@ impl<T: Clone> Clone for DerefWrapperWithClone<T> { *self = Self(source.0.clone()); } } + +#[cfg(test)] +mod test { + #[derive(Default)] + struct Data { + field: String, + } + + fn test_data() -> Data { + Data { + field: "default_value".to_string(), + } + } + + #[test] + fn test() { + let mut data = test_data(); + data.field = "override_value".to_owned(); + } +} diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr index f7e659b10de..329be4d3662 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr @@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/complex_conditionals_nested.rs:13:13 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some(<item>) = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index ddd600418af..f7e338935a7 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -2,7 +2,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some(<item>) = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ @@ -17,7 +17,7 @@ error: called `expect` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:49:9 | LL | if x.is_some() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some(<item>) = x` ... LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ error: called `unwrap` on `x` after checking its variant with `is_none` --> tests/ui/checked_unwrap/simple_conditionals.rs:65:9 | LL | if x.is_none() { - | -------------- help: try: `if let Some(..) = x` + | -------------- help: try: `if let Some(<item>) = x` ... LL | x.unwrap(); | ^^^^^^^^^^ @@ -68,7 +68,7 @@ error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13 | LL | if $a.is_some() { - | --------------- help: try: `if let Some(..) = x` + | --------------- help: try: `if let Some(<item>) = x` LL | // unnecessary LL | $a.unwrap(); | ^^^^^^^^^^^ @@ -82,7 +82,7 @@ error: called `unwrap` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:78:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Ok(..) = x` + | ------------ help: try: `if let Ok(<item>) = x` LL | // unnecessary LL | x.unwrap(); | ^^^^^^^^^^ @@ -91,7 +91,7 @@ error: called `expect` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Ok(..) = x` + | ------------ help: try: `if let Ok(<item>) = x` ... LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:94:9 | LL | if x.is_ok() { - | ------------ help: try: `if let Err(..) = x` + | ------------ help: try: `if let Err(<item>) = x` ... LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ error: called `unwrap_err` on `x` after checking its variant with `is_err` --> tests/ui/checked_unwrap/simple_conditionals.rs:102:9 | LL | if x.is_err() { - | ------------- help: try: `if let Err(..) = x` + | ------------- help: try: `if let Err(<item>) = x` ... LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ error: called `unwrap` on `x` after checking its variant with `is_err` --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9 | LL | if x.is_err() { - | ------------- help: try: `if let Ok(..) = x` + | ------------- help: try: `if let Ok(<item>) = x` ... LL | x.unwrap(); | ^^^^^^^^^^ @@ -172,7 +172,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:134:9 | LL | if option.is_some() { - | ------------------- help: try: `if let Some(..) = &option` + | ------------------- help: try: `if let Some(<item>) = &option` LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:144:9 | LL | if result.is_ok() { - | ----------------- help: try: `if let Ok(..) = &result` + | ----------------- help: try: `if let Ok(<item>) = &result` LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +206,7 @@ error: called `unwrap` on `option` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9 | LL | if option.is_some() { - | ------------------- help: try: `if let Some(..) = &mut option` + | ------------------- help: try: `if let Some(<item>) = &mut option` LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +223,7 @@ error: called `unwrap` on `result` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9 | LL | if result.is_ok() { - | ----------------- help: try: `if let Ok(..) = &mut result` + | ----------------- help: try: `if let Ok(<item>) = &mut result` LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr index 01944baee79..1da78b56239 100644 --- a/src/tools/clippy/tests/ui/collapsible_match.stderr +++ b/src/tools/clippy/tests/ui/collapsible_match.stderr @@ -223,7 +223,7 @@ help: the outer pattern can be modified to include the inner pattern LL | if let Issue9647::A { a, .. } = x { | ^ replace this binding LL | if let Some(u) = a { - | ^^^^^^^ with this pattern, prefixed by a: + | ^^^^^^^ with this pattern, prefixed by `a`: error: this `if let` can be collapsed into the outer `if let` --> tests/ui/collapsible_match.rs:292:9 diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.fixed b/src/tools/clippy/tests/ui/crashes/ice-3717.fixed new file mode 100644 index 00000000000..3f54b326979 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.fixed @@ -0,0 +1,11 @@ +#![deny(clippy::implicit_hasher)] + +use std::collections::HashSet; + +fn main() {} + +pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) { + //~^ ERROR: parameter of type `HashSet` should be generalized over different hashers + let _ = [0u8; 0]; + let _: HashSet<usize> = HashSet::default(); +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.rs b/src/tools/clippy/tests/ui/crashes/ice-3717.rs index 770f6cf448a..2890a9277c7 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3717.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.rs @@ -1,7 +1,5 @@ #![deny(clippy::implicit_hasher)] -//@no-rustfix: need to change the suggestion to a multipart suggestion - use std::collections::HashSet; fn main() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr index 4b4618ee1bb..aac72c66965 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr @@ -1,5 +1,5 @@ error: parameter of type `HashSet` should be generalized over different hashers - --> tests/ui/crashes/ice-3717.rs:9:21 + --> tests/ui/crashes/ice-3717.rs:7:21 | LL | pub fn ice_3717(_: &HashSet<usize>) { | ^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs index 56a8d22cb1c..9dafad8b784 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::fmt::Display; +use std::ptr; use std::sync::atomic::AtomicUsize; use std::sync::Once; @@ -53,4 +54,20 @@ mod issue_8493 { issue_8493!(); } +#[repr(C, align(8))] +struct NoAtomic(usize); +#[repr(C, align(8))] +struct WithAtomic(AtomicUsize); + +const fn with_non_null() -> *const WithAtomic { + const NO_ATOMIC: NoAtomic = NoAtomic(0); + (&NO_ATOMIC as *const NoAtomic).cast() +} +const WITH_ATOMIC: *const WithAtomic = with_non_null(); + +struct Generic<T>(T); +impl<T> Generic<T> { + const RAW_POINTER: *const Cell<T> = ptr::null(); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr index 1f2b9561ce5..4a725147142 100644 --- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr +++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.stderr @@ -1,5 +1,5 @@ error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:9:1 + --> tests/ui/declare_interior_mutable_const/others.rs:10:1 | LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); = help: to override `-D warnings` add `#[allow(clippy::declare_interior_mutable_const)]` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:10:1 + --> tests/ui/declare_interior_mutable_const/others.rs:11:1 | LL | const CELL: Cell<usize> = Cell::new(6); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const CELL: Cell<usize> = Cell::new(6); = help: consider making this `Sync` so that it can go in a static item or using a `thread_local` error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:11:1 + --> tests/ui/declare_interior_mutable_const/others.rs:12:1 | LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], V = help: consider making this a static item error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:16:9 + --> tests/ui/declare_interior_mutable_const/others.rs:17:9 | LL | const $name: $ty = $e; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | declare_const!(_ONCE: Once = Once::new()); = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: a `const` item should not be interior mutable - --> tests/ui/declare_interior_mutable_const/others.rs:44:13 + --> tests/ui/declare_interior_mutable_const/others.rs:45:13 | LL | const _BAZ: Cell<usize> = Cell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed new file mode 100644 index 00000000000..fb0f40b34a4 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.fixed @@ -0,0 +1,13 @@ +// This test checks that words starting with capital letters and ending with "ified" don't +// trigger the lint. + +#![deny(clippy::doc_markdown)] + +pub enum OutputFormat { + /// `HumaNified` + //~^ ERROR: item in documentation is missing backticks + Plain, + // Should not warn! + /// JSONified console output + Json, +} diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs new file mode 100644 index 00000000000..8c1e1a3cd6c --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.rs @@ -0,0 +1,13 @@ +// This test checks that words starting with capital letters and ending with "ified" don't +// trigger the lint. + +#![deny(clippy::doc_markdown)] + +pub enum OutputFormat { + /// HumaNified + //~^ ERROR: item in documentation is missing backticks + Plain, + // Should not warn! + /// JSONified console output + Json, +} diff --git a/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr new file mode 100644 index 00000000000..ae68a767ec9 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_markdown-issue_13097.stderr @@ -0,0 +1,18 @@ +error: item in documentation is missing backticks + --> tests/ui/doc/doc_markdown-issue_13097.rs:7:9 + | +LL | /// HumaNified + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/doc/doc_markdown-issue_13097.rs:4:9 + | +LL | #![deny(clippy::doc_markdown)] + | ^^^^^^^^^^^^^^^^^^^^ +help: try + | +LL | /// `HumaNified` + | ~~~~~~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/double_must_use.rs b/src/tools/clippy/tests/ui/double_must_use.rs index 615de3e2474..4460aeb075b 100644 --- a/src/tools/clippy/tests/ui/double_must_use.rs +++ b/src/tools/clippy/tests/ui/double_must_use.rs @@ -3,19 +3,19 @@ #[must_use] pub fn must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } #[must_use] pub fn must_use_tuple() -> (Result<(), ()>, u8) { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } #[must_use] pub fn must_use_array() -> [Result<(), ()>; 1] { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already unimplemented!(); } @@ -32,7 +32,7 @@ async fn async_must_use() -> usize { #[must_use] async fn async_must_use_result() -> Result<(), ()> { - //~^ ERROR: this function has an empty `#[must_use]` attribute, but returns a type already + //~^ ERROR: this function has a `#[must_use]` attribute with no message, but returns a type already Ok(()) } diff --git a/src/tools/clippy/tests/ui/double_must_use.stderr b/src/tools/clippy/tests/ui/double_must_use.stderr index 0f2154ecbcf..b26d1e48a8b 100644 --- a/src/tools/clippy/tests/ui/double_must_use.stderr +++ b/src/tools/clippy/tests/ui/double_must_use.stderr @@ -1,36 +1,36 @@ -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:5:1 | LL | pub fn must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute = note: `-D clippy::double-must-use` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:11:1 | LL | pub fn must_use_tuple() -> (Result<(), ()>, u8) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:17:1 | LL | pub fn must_use_array() -> [Result<(), ()>; 1] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute -error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` +error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]` --> tests/ui/double_must_use.rs:34:1 | LL | async fn async_must_use_result() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: either add some descriptive text or remove the attribute + = help: either add some descriptive message or remove the attribute error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed index f38b34c5a7c..1148f0f6c6a 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed @@ -153,3 +153,15 @@ fn main() { let r = &x; for _ in r {} } + +#[clippy::msrv = "1.79"] +pub fn issue_13184() { + // https://github.com/rust-lang/rust-clippy/issues/13184 + // No need to fix, as IntoIterator for Box is valid starting from 1.80 + let mut values: Box<[u32]> = Box::new([1, 2]); + for _ in values.iter() {} + for _ in values.iter_mut() {} + + let rvalues = &values; + for _ in rvalues.iter() {} +} diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_iter_loop.rs index 2e701ada5ac..4dda2f13e5b 100644 --- a/src/tools/clippy/tests/ui/explicit_iter_loop.rs +++ b/src/tools/clippy/tests/ui/explicit_iter_loop.rs @@ -153,3 +153,15 @@ fn main() { let r = &x; for _ in r.iter() {} } + +#[clippy::msrv = "1.79"] +pub fn issue_13184() { + // https://github.com/rust-lang/rust-clippy/issues/13184 + // No need to fix, as IntoIterator for Box is valid starting from 1.80 + let mut values: Box<[u32]> = Box::new([1, 2]); + for _ in values.iter() {} + for _ in values.iter_mut() {} + + let rvalues = &values; + for _ in rvalues.iter() {} +} diff --git a/src/tools/clippy/tests/ui/floating_point_abs.fixed b/src/tools/clippy/tests/ui/floating_point_abs.fixed index 5312a8b29c6..33183c76972 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.fixed +++ b/src/tools/clippy/tests/ui/floating_point_abs.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_abs.rs b/src/tools/clippy/tests/ui/floating_point_abs.rs index 8619177130c..a08d5bbcef5 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.rs +++ b/src/tools/clippy/tests/ui/floating_point_abs.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_abs.stderr b/src/tools/clippy/tests/ui/floating_point_abs.stderr index f5a778c5b76..0c1f68f3b7f 100644 --- a/src/tools/clippy/tests/ui/floating_point_abs.stderr +++ b/src/tools/clippy/tests/ui/floating_point_abs.stderr @@ -1,5 +1,5 @@ error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:15:5 + --> tests/ui/floating_point_abs.rs:14:5 | LL | if num >= 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` @@ -8,43 +8,43 @@ LL | if num >= 0.0 { num } else { -num } = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:19:5 + --> tests/ui/floating_point_abs.rs:18:5 | LL | if 0.0 < num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:23:5 + --> tests/ui/floating_point_abs.rs:22:5 | LL | if a.a > 0.0 { a.a } else { -a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:27:5 + --> tests/ui/floating_point_abs.rs:26:5 | LL | if 0.0 >= num { -num } else { num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:31:5 + --> tests/ui/floating_point_abs.rs:30:5 | LL | if a.a < 0.0 { -a.a } else { a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:35:5 + --> tests/ui/floating_point_abs.rs:34:5 | LL | if num < 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:39:5 + --> tests/ui/floating_point_abs.rs:38:5 | LL | if 0.0 >= num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:44:12 + --> tests/ui/floating_point_abs.rs:43:12 | LL | a: if a.a >= 0.0 { -a.a } else { a.a }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed index 3ce2edf2c71..164aac2601a 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.rs b/src/tools/clippy/tests/ui/floating_point_mul_add.rs index b5e4a8db4db..ae024b7f224 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.rs +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_ops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr index 3e1a071de73..9c75909f715 100644 --- a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr +++ b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr @@ -1,5 +1,5 @@ error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:20:13 + --> tests/ui/floating_point_mul_add.rs:19:13 | LL | let _ = a * b + c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` @@ -8,73 +8,73 @@ LL | let _ = a * b + c; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:21:13 + --> tests/ui/floating_point_mul_add.rs:20:13 | LL | let _ = a * b - c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:22:13 + --> tests/ui/floating_point_mul_add.rs:21:13 | LL | let _ = c + a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:23:13 + --> tests/ui/floating_point_mul_add.rs:22:13 | LL | let _ = c - a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:24:13 + --> tests/ui/floating_point_mul_add.rs:23:13 | LL | let _ = a + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:25:13 + --> tests/ui/floating_point_mul_add.rs:24:13 | LL | let _ = a + 2. * 4.; | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:27:13 + --> tests/ui/floating_point_mul_add.rs:26:13 | LL | let _ = (a * b) + c; | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:28:13 + --> tests/ui/floating_point_mul_add.rs:27:13 | LL | let _ = c + (a * b); | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:29:13 + --> tests/ui/floating_point_mul_add.rs:28:13 | LL | let _ = a * b * c + d; | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:31:13 + --> tests/ui/floating_point_mul_add.rs:30:13 | LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:32:13 + --> tests/ui/floating_point_mul_add.rs:31:13 | LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:34:13 + --> tests/ui/floating_point_mul_add.rs:33:13 | LL | let _ = (a * a + b).sqrt(); | ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)` error: multiply and add expressions can be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:37:13 + --> tests/ui/floating_point_mul_add.rs:36:13 | LL | let _ = a - (b * u as f64); | ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)` diff --git a/src/tools/clippy/tests/ui/floating_point_rad.fixed b/src/tools/clippy/tests/ui/floating_point_rad.fixed index a710bd9bd60..2f93d233cb4 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.fixed +++ b/src/tools/clippy/tests/ui/floating_point_rad.fixed @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_flops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_rad.rs b/src/tools/clippy/tests/ui/floating_point_rad.rs index 14656f021df..9690effc4e1 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.rs +++ b/src/tools/clippy/tests/ui/floating_point_rad.rs @@ -1,4 +1,3 @@ -#![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] /// Allow suboptimal_flops in constant context diff --git a/src/tools/clippy/tests/ui/floating_point_rad.stderr b/src/tools/clippy/tests/ui/floating_point_rad.stderr index 64674342c2b..b834f5374e0 100644 --- a/src/tools/clippy/tests/ui/floating_point_rad.stderr +++ b/src/tools/clippy/tests/ui/floating_point_rad.stderr @@ -1,5 +1,5 @@ error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:11:13 + --> tests/ui/floating_point_rad.rs:10:13 | LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_radians()` @@ -8,43 +8,43 @@ LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:12:13 + --> tests/ui/floating_point_rad.rs:11:13 | LL | let _ = degrees as f64 * 180.0 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:17:13 + --> tests/ui/floating_point_rad.rs:16:13 | LL | let _ = x * 180f32 / std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:18:13 + --> tests/ui/floating_point_rad.rs:17:13 | LL | let _ = 90. * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:19:13 + --> tests/ui/floating_point_rad.rs:18:13 | LL | let _ = 90.5 * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_degrees()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:20:13 + --> tests/ui/floating_point_rad.rs:19:13 | LL | let _ = x * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:21:13 + --> tests/ui/floating_point_rad.rs:20:13 | LL | let _ = 90. * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:22:13 + --> tests/ui/floating_point_rad.rs:21:13 | LL | let _ = 90.5 * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_radians()` diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed index 5778f8f526f..4c324587c96 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.fixed @@ -15,6 +15,14 @@ struct Foo { z: i32, } +#[derive(Default)] +#[allow(clippy::inconsistent_struct_constructor)] +struct Bar { + x: i32, + y: i32, + z: i32, +} + mod without_base { use super::Foo; @@ -70,4 +78,17 @@ mod with_base { } } +mod with_allow_ty_def { + use super::Bar; + + fn test() { + let x = 1; + let y = 1; + let z = 1; + + // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]` + Bar { y, x, z }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs index 9efaf068934..d49f236b9b0 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.rs @@ -15,6 +15,14 @@ struct Foo { z: i32, } +#[derive(Default)] +#[allow(clippy::inconsistent_struct_constructor)] +struct Bar { + x: i32, + y: i32, + z: i32, +} + mod without_base { use super::Foo; @@ -74,4 +82,17 @@ mod with_base { } } +mod with_allow_ty_def { + use super::Bar; + + fn test() { + let x = 1; + let y = 1; + let z = 1; + + // Should NOT lint because `Bar` is defined with `#[allow(clippy::inconsistent_struct_constructor)]` + Bar { y, x, z }; + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr index 1192271f911..97bb7c789a7 100644 --- a/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr +++ b/src/tools/clippy/tests/ui/inconsistent_struct_constructor.stderr @@ -1,5 +1,5 @@ error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui/inconsistent_struct_constructor.rs:28:9 + --> tests/ui/inconsistent_struct_constructor.rs:36:9 | LL | Foo { y, x, z }; | ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }` @@ -8,7 +8,7 @@ LL | Foo { y, x, z }; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_struct_constructor)]` error: struct constructor field order is inconsistent with struct definition field order - --> tests/ui/inconsistent_struct_constructor.rs:55:9 + --> tests/ui/inconsistent_struct_constructor.rs:63:9 | LL | / Foo { LL | | z, diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs index 2dccadd9fce..c8409d78ed7 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs @@ -17,7 +17,7 @@ mod multiple { //~^ ERROR: `clippy::msrv` is defined multiple times mod foo { - #![clippy::msrv = "1"] + #![clippy::msrv = "1.0"] #![clippy::msrv = "1.0.0"] //~^ ERROR: `clippy::msrv` is defined multiple times } diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr index b4cb1b5713f..dbc276ed89d 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr @@ -31,8 +31,8 @@ LL | #![clippy::msrv = "1.0.0"] note: first definition found here --> tests/ui/min_rust_version_invalid_attr.rs:20:9 | -LL | #![clippy::msrv = "1"] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #![clippy::msrv = "1.0"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs index 440a86b104a..1d1911aaa1d 100644 --- a/src/tools/clippy/tests/ui/string_slice.rs +++ b/src/tools/clippy/tests/ui/string_slice.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + #[warn(clippy::string_slice)] #[allow(clippy::no_effect)] @@ -11,4 +13,7 @@ fn main() { let s = String::from(m); &s[0..2]; //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character + let a = Cow::Borrowed("foo"); + &a[0..3]; + //~^ ERROR: indexing into a string may panic if the index is within a UTF-8 character } diff --git a/src/tools/clippy/tests/ui/string_slice.stderr b/src/tools/clippy/tests/ui/string_slice.stderr index 7a4596b5f2d..bc0fcde34b8 100644 --- a/src/tools/clippy/tests/ui/string_slice.stderr +++ b/src/tools/clippy/tests/ui/string_slice.stderr @@ -1,5 +1,5 @@ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:5:6 + --> tests/ui/string_slice.rs:7:6 | LL | &"Ölkanne"[1..]; | ^^^^^^^^^^^^^^ @@ -8,16 +8,22 @@ LL | &"Ölkanne"[1..]; = help: to override `-D warnings` add `#[allow(clippy::string_slice)]` error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:9:6 + --> tests/ui/string_slice.rs:11:6 | LL | &m[2..5]; | ^^^^^^^ error: indexing into a string may panic if the index is within a UTF-8 character - --> tests/ui/string_slice.rs:12:6 + --> tests/ui/string_slice.rs:14:6 | LL | &s[0..2]; | ^^^^^^^ -error: aborting due to 3 previous errors +error: indexing into a string may panic if the index is within a UTF-8 character + --> tests/ui/string_slice.rs:17:6 + | +LL | &a[0..3]; + | ^^^^^^^ + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed new file mode 100644 index 00000000000..d4a0cdf3447 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.fixed @@ -0,0 +1,9 @@ +#![warn(clippy::too_long_first_doc_paragraph)] + +/// A very short summary. +/// +/// A much longer explanation that goes into a lot more detail about +/// how the thing works, possibly with doclinks and so one, +/// and probably spanning a many rows. Blablabla, it needs to be over +/// 200 characters so I needed to write something longeeeeeeer. +pub struct Foo; diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs new file mode 100644 index 00000000000..5a3b6c42a32 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.rs @@ -0,0 +1,8 @@ +#![warn(clippy::too_long_first_doc_paragraph)] + +/// A very short summary. +/// A much longer explanation that goes into a lot more detail about +/// how the thing works, possibly with doclinks and so one, +/// and probably spanning a many rows. Blablabla, it needs to be over +/// 200 characters so I needed to write something longeeeeeeer. +pub struct Foo; diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr new file mode 100644 index 00000000000..6403265a39c --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph-fix.stderr @@ -0,0 +1,20 @@ +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph-fix.rs:3:1 + | +LL | / /// A very short summary. +LL | | /// A much longer explanation that goes into a lot more detail about +LL | | /// how the thing works, possibly with doclinks and so one, +LL | | /// and probably spanning a many rows. Blablabla, it needs to be over +LL | | /// 200 characters so I needed to write something longeeeeeeer. + | |_ + | + = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]` +help: add an empty line + | +LL ~ /// A very short summary. +LL + /// + | + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs new file mode 100644 index 00000000000..1042249c5b7 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs @@ -0,0 +1,53 @@ +//@no-rustfix + +#![warn(clippy::too_long_first_doc_paragraph)] + +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub struct Bar; + +// Should not warn! (not an item visible on mod page) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +impl Bar {} + +// Should not warn! (less than 80 characters) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. +/// +/// Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub enum Enum { + A, +} + +/// Lorem +/// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub union Union { + a: u8, + b: u8, +} + +// Should not warn! (title) +/// # bla +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +pub union Union2 { + a: u8, + b: u8, +} + +// Should not warn! (not public) +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +/// gravida non lacinia at, rhoncus eu lacus. +fn f() {} + +fn main() { + // test code goes here +} diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr new file mode 100644 index 00000000000..7f48e5cf884 --- /dev/null +++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr @@ -0,0 +1,22 @@ +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph.rs:5:1 + | +LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +LL | | /// gravida non lacinia at, rhoncus eu lacus. + | |_ + | + = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]` + +error: first doc comment paragraph is too long + --> tests/ui/too_long_first_doc_paragraph.rs:26:1 + | +LL | / /// Lorem +LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia +LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero, +LL | | /// gravida non lacinia at, rhoncus eu lacus. + | |_ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr index fcd60f48bcc..bcdf65b217e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr @@ -2,316 +2,432 @@ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:83:13 | LL | let _ = opt.unwrap_or_else(|| 2); - | ^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]` +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:84:13 | LL | let _ = opt.unwrap_or_else(|| astronomers_pi); - | ^^^^--------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:85:13 | LL | let _ = opt.unwrap_or_else(|| ext_str.some_field); - | ^^^^------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = opt.unwrap_or(ext_str.some_field); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:87:13 | LL | let _ = opt.and_then(|_| ext_opt); - | ^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = opt.and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:88:13 | LL | let _ = opt.or_else(|| ext_opt); - | ^^^^------------------- - | | - | help: use `or(..)` instead: `or(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(ext_opt); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:89:13 | LL | let _ = opt.or_else(|| None); - | ^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:90:13 | LL | let _ = opt.get_or_insert_with(|| 2); - | ^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = opt.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:91:13 | LL | let _ = opt.ok_or_else(|| 2); - | ^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _ = opt.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:92:13 | LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2))); - | ^^^^^^^^^^^^^^^^^------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = nested_tuple_opt.unwrap_or(Some((1, 2))); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:93:13 | LL | let _ = cond.then(|| astronomers_pi); - | ^^^^^----------------------- - | | - | help: use `then_some(..)` instead: `then_some(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = cond.then_some(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:94:13 | LL | let _ = true.then(|| -> _ {}); - | ^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some({})` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({}); + | ~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:95:13 | LL | let _ = true.then(|| {}); - | ^^^^^----------- - | | - | help: use `then_some(..)` instead: `then_some({})` + | ^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({}); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:99:13 | LL | let _ = Some(1).unwrap_or_else(|| *r); - | ^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(*r)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).unwrap_or(*r); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:101:13 | LL | let _ = Some(1).unwrap_or_else(|| *b); - | ^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(*b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).unwrap_or(*b); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:103:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r); - | ^^^^^^^^^^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(&r)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).as_ref().unwrap_or(&r); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:104:13 | LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b); - | ^^^^^^^^^^^^^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(&b)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(1).as_ref().unwrap_or(&b); + | ~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:107:13 | LL | let _ = Some(10).unwrap_or_else(|| 2); - | ^^^^^^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Some(10).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:108:13 | LL | let _ = Some(10).and_then(|_| ext_opt); - | ^^^^^^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = Some(10).and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:109:28 | LL | let _: Option<usize> = None.or_else(|| ext_opt); - | ^^^^^------------------- - | | - | help: use `or(..)` instead: `or(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option<usize> = None.or(ext_opt); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:110:13 | LL | let _ = None.get_or_insert_with(|| 2); - | ^^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = None.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:111:35 | LL | let _: Result<usize, usize> = None.ok_or_else(|| 2); - | ^^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _: Result<usize, usize> = None.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:112:28 | LL | let _: Option<usize> = None.or_else(|| None); - | ^^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option<usize> = None.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:115:13 | LL | let _ = deep.0.unwrap_or_else(|| 2); - | ^^^^^^^-------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = deep.0.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:116:13 | LL | let _ = deep.0.and_then(|_| ext_opt); - | ^^^^^^^--------------------- - | | - | help: use `and(..)` instead: `and(ext_opt)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _ = deep.0.and(ext_opt); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:117:13 | LL | let _ = deep.0.or_else(|| None); - | ^^^^^^^---------------- - | | - | help: use `or(..)` instead: `or(None)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = deep.0.or(None); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:118:13 | LL | let _ = deep.0.get_or_insert_with(|| 2); - | ^^^^^^^------------------------ - | | - | help: use `get_or_insert(..)` instead: `get_or_insert(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `get_or_insert` instead + | +LL | let _ = deep.0.get_or_insert(2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:119:13 | LL | let _ = deep.0.ok_or_else(|| 2); - | ^^^^^^^---------------- - | | - | help: use `ok_or(..)` instead: `ok_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `ok_or` instead + | +LL | let _ = deep.0.ok_or(2); + | ~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:150:28 | LL | let _: Option<usize> = None.or_else(|| Some(3)); - | ^^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Option<usize> = None.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:151:13 | LL | let _ = deep.0.or_else(|| Some(3)); - | ^^^^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = deep.0.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Option::None` --> tests/ui/unnecessary_lazy_eval.rs:152:13 | LL | let _ = opt.or_else(|| Some(3)); - | ^^^^------------------- - | | - | help: use `or(..)` instead: `or(Some(3))` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _ = opt.or(Some(3)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:158:13 | LL | let _ = res2.unwrap_or_else(|_| 2); - | ^^^^^--------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:159:13 | LL | let _ = res2.unwrap_or_else(|_| astronomers_pi); - | ^^^^^---------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(astronomers_pi); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:160:13 | LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field); - | ^^^^^-------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = res2.unwrap_or(ext_str.some_field); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:182:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(2)); - | ^^^^-------------------- - | | - | help: use `and(..)` instead: `and(Err(2))` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result<usize, usize> = res.and(Err(2)); + | ~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:183:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi)); - | ^^^^--------------------------------- - | | - | help: use `and(..)` instead: `and(Err(astronomers_pi))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result<usize, usize> = res.and(Err(astronomers_pi)); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:184:35 | LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field)); - | ^^^^------------------------------------- - | | - | help: use `and(..)` instead: `and(Err(ext_str.some_field))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `and` instead + | +LL | let _: Result<usize, usize> = res.and(Err(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:186:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2)); - | ^^^^------------------ - | | - | help: use `or(..)` instead: `or(Ok(2))` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result<usize, usize> = res.or(Ok(2)); + | ~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:187:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi)); - | ^^^^------------------------------- - | | - | help: use `or(..)` instead: `or(Ok(astronomers_pi))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result<usize, usize> = res.or(Ok(astronomers_pi)); + | ~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:188:35 | LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field)); - | ^^^^----------------------------------- - | | - | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `or` instead + | +LL | let _: Result<usize, usize> = res.or(Ok(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval.rs:189:35 @@ -324,193 +440,265 @@ LL | | // some lines ... | LL | | // some lines LL | | or_else(|_| Ok(ext_str.some_field)); - | |_____----------------------------------^ - | | - | help: use `or(..)` instead: `or(Ok(ext_str.some_field))` + | |_______________________________________^ + | +help: use `or` instead + | +LL | or(Ok(ext_str.some_field)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:219:14 | LL | let _x = false.then(|| i32::MAX + 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX + 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:221:14 | LL | let _x = false.then(|| i32::MAX * 2); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX * 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX * 2); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:223:14 | LL | let _x = false.then(|| i32::MAX - 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX - 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX - 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:225:14 | LL | let _x = false.then(|| i32::MIN - 1); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN - 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN - 1); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:227:14 | LL | let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2); - | ^^^^^^------------------------------------- - | | - | help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some((1 + 2 * 3 - 2 / 3 + 9) << 2); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:229:14 | LL | let _x = false.then(|| 255u8 << 7); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 << 7)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 << 7); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:231:14 | LL | let _x = false.then(|| 255u8 << 8); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 << 8)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 << 8); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:233:14 | LL | let _x = false.then(|| 255u8 >> 8); - | ^^^^^^------------------- - | | - | help: use `then_some(..)` instead: `then_some(255u8 >> 8)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255u8 >> 8); + | ~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:236:14 | LL | let _x = false.then(|| i32::MAX + -1); - | ^^^^^^---------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MAX + -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MAX + -1); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:238:14 | LL | let _x = false.then(|| -i32::MAX); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(-i32::MAX)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(-i32::MAX); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:240:14 | LL | let _x = false.then(|| -i32::MIN); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(-i32::MIN)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(-i32::MIN); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:243:14 | LL | let _x = false.then(|| 255 >> -7); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(255 >> -7)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255 >> -7); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:245:14 | LL | let _x = false.then(|| 255 << -1); - | ^^^^^^------------------ - | | - | help: use `then_some(..)` instead: `then_some(255 << -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(255 << -1); + | ~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:247:14 | LL | let _x = false.then(|| 1 / 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(1 / 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(1 / 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:249:14 | LL | let _x = false.then(|| x << -1); - | ^^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some(x << -1)` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x << -1); + | ~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:251:14 | LL | let _x = false.then(|| x << 2); - | ^^^^^^--------------- - | | - | help: use `then_some(..)` instead: `then_some(x << 2)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x << 2); + | ~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:261:14 | LL | let _x = false.then(|| x / 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(x / 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x / 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:263:14 | LL | let _x = false.then(|| x % 0); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(x % 0)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(x % 0); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:266:14 | LL | let _x = false.then(|| 1 / -1); - | ^^^^^^--------------- - | | - | help: use `then_some(..)` instead: `then_some(1 / -1)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(1 / -1); + | ~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:268:14 | LL | let _x = false.then(|| i32::MIN / -1); - | ^^^^^^---------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN / -1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN / -1); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:271:14 | LL | let _x = false.then(|| i32::MIN / 0); - | ^^^^^^--------------------- - | | - | help: use `then_some(..)` instead: `then_some(i32::MIN / 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(i32::MIN / 0); + | ~~~~~~~~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:273:14 | LL | let _x = false.then(|| 4 / 2); - | ^^^^^^-------------- - | | - | help: use `then_some(..)` instead: `then_some(4 / 2)` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(4 / 2); + | ~~~~~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval.rs:281:14 | LL | let _x = false.then(|| f1 + f2); - | ^^^^^^---------------- - | | - | help: use `then_some(..)` instead: `then_some(f1 + f2)` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _x = false.then_some(f1 + f2); + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 63 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr index b566b119571..390235b2124 100644 --- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval_unfixable.stderr @@ -2,36 +2,47 @@ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:13:13 | LL | let _ = Ok(1).unwrap_or_else(|()| 2); - | ^^^^^^---------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]` +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:19:13 | LL | let _ = Ok(1).unwrap_or_else(|e::E| 2); - | ^^^^^^------------------------ - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used to substitute value for `Result::Err` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:21:13 | LL | let _ = Ok(1).unwrap_or_else(|SomeStruct { .. }| 2); - | ^^^^^^------------------------------------- - | | - | help: use `unwrap_or(..)` instead: `unwrap_or(2)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `unwrap_or` instead + | +LL | let _ = Ok(1).unwrap_or(2); + | ~~~~~~~~~~~~ error: unnecessary closure used with `bool::then` --> tests/ui/unnecessary_lazy_eval_unfixable.rs:31:13 | LL | let _ = true.then(|| -> &[u8] { &[] }); - | ^^^^^------------------------- - | | - | help: use `then_some(..)` instead: `then_some({ &[] })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `then_some` instead + | +LL | let _ = true.then_some({ &[] }); + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index dcf00e4e384..99b3560a064 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -20,6 +20,7 @@ new_pr = true [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ + "flip1995", "matthiaskrgr", "giraffate", ] diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html index 300c9de178f..f3d7e504fdf 100644 --- a/src/tools/clippy/util/gh-pages/index.html +++ b/src/tools/clippy/util/gh-pages/index.html @@ -23,378 +23,25 @@ Otherwise, have a great day =^.^= <link id="styleHighlight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/highlight.css"> <link id="styleNight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/tomorrow-night.css" disabled="true"> <link id="styleAyu" rel="stylesheet" href="https://rust-lang.github.io/mdBook/ayu-highlight.css" disabled="true"> - <style> - blockquote { font-size: 1em; } - [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; } - - .dropdown-menu { - color: var(--fg); - background: var(--theme-popup-bg); - border: 1px solid var(--theme-popup-border); - } - - .dropdown-menu .divider { - background-color: var(--theme-popup-border); - } - - .dropdown-menu .checkbox { - display: block; - white-space: nowrap; - margin: 0; - } - .dropdown-menu .checkbox label { - padding: 3px 20px; - width: 100%; - } - - .dropdown-menu .checkbox input { - position: relative; - margin: 0 0.5rem 0; - padding: 0; - } - - .dropdown-menu .checkbox:hover { - background-color: var(--theme-hover); - } - - div.panel div.panel-body button { - background: var(--searchbar-bg); - color: var(--searchbar-fg); - border-color: var(--theme-popup-border); - } - - div.panel div.panel-body button:hover { - box-shadow: 0 0 3px var(--searchbar-shadow-color); - } - - div.panel div.panel-body button.open { - filter: brightness(90%); - } - - .dropdown-toggle .badge { - background-color: #777; - } - - .panel-heading { cursor: pointer; } - - .panel-title { display: flex; flex-wrap: wrap;} - .panel-title .label { display: inline-block; } - - .panel-title-name { flex: 1; min-width: 400px;} - .panel-title-name span { vertical-align: bottom; } - - .panel .panel-title-name .anchor { display: none; } - .panel:hover .panel-title-name .anchor { display: inline;} - - .search-control { - margin-top: 15px; - } - - @media (min-width: 992px) { - .search-control { - margin-top: 0; - } - } - - @media (min-width: 405px) { - #upper-filters { - display: flex; - flex-wrap: wrap; - } - } - - @media (max-width: 430px) { - /* Turn the version filter list to the left */ - #version-filter-selector { - right: 0; - left: auto; - } - } - - @media (max-width: 412px) { - #upper-filters, - .panel-body .search-control { - padding-right: 8px; - padding-left: 8px; - } - } - - .label { - padding-top: 0.3em; - padding-bottom: 0.3em; - } - - .label-lint-group { - min-width: 8em; - } - .label-lint-level { - min-width: 4em; - } - - .label-lint-level-allow { - background-color: #5cb85c; - } - .label-lint-level-warn { - background-color: #f0ad4e; - } - .label-lint-level-deny { - background-color: #d9534f; - } - .label-lint-level-none { - background-color: #777777; - opacity: 0.5; - } - - .label-group-deprecated { - opacity: 0.5; - } - - .label-doc-folding { - color: #000; - background-color: #fff; - border: 1px solid var(--theme-popup-border); - } - .label-doc-folding:hover { - background-color: #e6e6e6; - } - - .lint-doc-md > h3 { - border-top: 1px solid var(--theme-popup-border); - padding: 10px 15px; - margin: 0 -15px; - font-size: 18px; - } - .lint-doc-md > h3:first-child { - border-top: none; - padding-top: 0px; - } - - @media (max-width:749px) { - .lint-additional-info-container { - display: flex; - flex-flow: column; - } - .lint-additional-info-item + .lint-additional-info-item { - border-top: 1px solid var(--theme-popup-border); - } - } - @media (min-width:750px) { - .lint-additional-info-container { - display: flex; - flex-flow: row; - } - .lint-additional-info-item + .lint-additional-info-item { - border-left: 1px solid var(--theme-popup-border); - } - } - - .lint-additional-info-item { - display: inline-flex; - min-width: 200px; - flex-grow: 1; - padding: 9px 5px 5px 15px; - } - - .label-applicability { - background-color: #777777; - margin: auto 5px; - } - - .label-version { - background-color: #777777; - margin: auto 5px; - font-family: monospace; - } - - details { - border-radius: 4px; - padding: .5em .5em 0; - } - - code { - white-space: pre !important; - } - - summary { - font-weight: bold; - margin: -.5em -.5em 0; - padding: .5em; - display: revert; - } - - details[open] { - padding: .5em; - } - </style> - <style> - /* Expanding the mdBoom theme*/ - .light { - --inline-code-bg: #f6f7f6; - } - .rust { - --inline-code-bg: #f6f7f6; - } - .coal { - --inline-code-bg: #1d1f21; - } - .navy { - --inline-code-bg: #1d1f21; - } - .ayu { - --inline-code-bg: #191f26; - } - - .theme-dropdown { - position: absolute; - margin: 0.7em; - z-index: 10; - } - - /* Applying the mdBook theme */ - .theme-icon { - text-align: center; - width: 2em; - height: 2em; - line-height: 2em; - border: solid 1px var(--icons); - border-radius: 5px; - user-select: none; - cursor: pointer; - } - .theme-icon:hover { - background: var(--theme-hover); - } - .theme-choice { - display: none; - list-style: none; - border: 1px solid var(--theme-popup-border); - border-radius: 5px; - color: var(--fg); - background: var(--theme-popup-bg); - padding: 0 0; - overflow: hidden; - } - - .theme-dropdown.open .theme-choice { - display: block; - } - - .theme-choice > li { - padding: 5px 10px; - font-size: 0.8em; - user-select: none; - cursor: pointer; - } - - .theme-choice > li:hover { - background: var(--theme-hover); - } - - .alert { - color: var(--fg); - background: var(--theme-hover); - border: 1px solid var(--theme-popup-border); - } - .page-header { - border-color: var(--theme-popup-border); - } - .panel-default > .panel-heading { - background: var(--theme-hover); - color: var(--fg); - border: 1px solid var(--theme-popup-border); - } - .panel-default > .panel-heading:hover { - filter: brightness(90%); - } - .list-group-item { - background: 0%; - border: 1px solid var(--theme-popup-border); - } - .panel, pre, hr { - background: var(--bg); - border: 1px solid var(--theme-popup-border); - } - - #version-filter-selector .checkbox { - display: flex; - } - - #version-filter { - min-width: available; - } - - #version-filter li label { - padding-right: 0; - width: 35%; - } - - .version-filter-input { - height: 60%; - width: 30%; - text-align: center; - border: none; - border-bottom: 1px solid #000000; - } - - #filter-label, .filter-clear { - background: var(--searchbar-bg); - color: var(--searchbar-fg); - border-color: var(--theme-popup-border); - filter: brightness(95%); - } - #filter-label:hover, .filter-clear:hover { - filter: brightness(90%); - } - .filter-input { - background: var(--searchbar-bg); - color: var(--searchbar-fg); - border-color: var(--theme-popup-border); - } - - .filter-input::-webkit-input-placeholder, - .filter-input::-moz-placeholder { - color: var(--searchbar-fg); - opacity: 30%; - } - - .expansion-group { - margin-top: 15px; - padding: 0px 8px; - display: flex; - flex-wrap: nowrap; - } - - @media (min-width: 992px) { - .expansion-group { - margin-top: 0; - padding: 0px 15px; - } - } - - .expansion-control { - width: 50%; - } - - :not(pre) > code { - color: var(--inline-code-color); - background-color: var(--inline-code-bg); - } - html { - scrollbar-color: var(--scrollbar) var(--bg); - } - body { - background: var(--bg); - color: var(--fg); - } - - </style> + <link rel="stylesheet" href="style.css"> </head> <body ng-app="clippy" ng-controller="lintList"> - <div theme-dropdown class="theme-dropdown"> - <div id="theme-icon" class="theme-icon">🖌</div> - <ul id="theme-menu" class="theme-choice"> - <li id="{{id}}" ng-repeat="(id, name) in themes" ng-click="selectTheme(id)">{{name}}</li> - </ul> + <div id="settings-dropdown"> + <div class="settings-icon" tabindex="-1"></div> + <div class="settings-menu" tabindex="-1"> + <div class="setting-radio-name">Theme</div> + <select id="theme-choice" onchange="setTheme(this.value, true)"> + <option value="ayu">Ayu</option> + <option value="coal">Coal</option> + <option value="light">Light</option> + <option value="navy">Navy</option> + <option value="rust">Rust</option> + </select> + <label> + <input type="checkbox" id="disable-shortcuts" onchange="changeSetting(this)"> + <span>Disable keyboard shortcuts</span> + </label> + </div> </div> <div class="container"> @@ -592,7 +239,7 @@ Otherwise, have a great day =^.^= <!-- Applicability --> <div class="lint-additional-info-item"> <span> Applicability: </span> - <span class="label label-default label-applicability">{{lint.applicability.applicability}}</span> + <span class="label label-default label-applicability">{{lint.applicability}}</span> <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a> </div> <!-- Clippy version --> @@ -605,8 +252,8 @@ Otherwise, have a great day =^.^= <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a> </div> <!-- Jump to source --> - <div class="lint-additional-info-item" ng-if="lint.id_span"> - <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/clippy_lints/{{lint.id_span.path}}#L{{lint.id_span.line}}">View Source</a> + <div class="lint-additional-info-item" ng-if="lint.id_location"> + <a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/{{lint.id_location}}">View Source</a> </div> </div> </div> diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js index ed1e090e1b5..1a5330bc0e5 100644 --- a/src/tools/clippy/util/gh-pages/script.js +++ b/src/tools/clippy/util/gh-pages/script.js @@ -50,24 +50,6 @@ ); }; }) - .directive('themeDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function () { - $element.toggleClass('open'); - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) .directive('filterDropdown', function ($document) { return { restrict: 'A', @@ -114,28 +96,19 @@ cargo: true, complexity: true, correctness: true, - deprecated: false, nursery: true, pedantic: true, perf: true, restriction: true, style: true, suspicious: true, + deprecated: false, } $scope.groups = { ...GROUPS_FILTER_DEFAULT }; - const THEMES_DEFAULT = { - light: "Light", - rust: "Rust", - coal: "Coal", - navy: "Navy", - ayu: "Ayu" - }; - $scope.themes = THEMES_DEFAULT; - $scope.versionFilters = { "≥": {enabled: false, minorVersion: null }, "≤": {enabled: false, minorVersion: null }, @@ -153,11 +126,10 @@ ); const APPLICABILITIES_FILTER_DEFAULT = { - Unspecified: true, - Unresolved: true, MachineApplicable: true, MaybeIncorrect: true, - HasPlaceholders: true + HasPlaceholders: true, + Unspecified: true, }; $scope.applicabilities = { @@ -321,10 +293,6 @@ $location.path($scope.search); } - $scope.selectTheme = function (theme) { - setTheme(theme, true); - } - $scope.toggleLevels = function (value) { const levels = $scope.levels; for (const key in levels) { @@ -456,7 +424,7 @@ } $scope.byApplicabilities = function (lint) { - return $scope.applicabilities[lint.applicability.applicability]; + return $scope.applicabilities[lint.applicability]; }; // Show details for one lint @@ -537,6 +505,16 @@ function getQueryVariable(variable) { } } +function storeValue(settingName, value) { + try { + localStorage.setItem(`clippy-lint-list-${settingName}`, value); + } catch (e) { } +} + +function loadValue(settingName) { + return localStorage.getItem(`clippy-lint-list-${settingName}`); +} + function setTheme(theme, store) { let enableHighlight = false; let enableNight = false; @@ -569,14 +547,14 @@ function setTheme(theme, store) { document.getElementById("styleAyu").disabled = !enableAyu; if (store) { - try { - localStorage.setItem('clippy-lint-list-theme', theme); - } catch (e) { } + storeValue("theme", theme); + } else { + document.getElementById(`theme-choice`).value = theme; } } function handleShortcut(ev) { - if (ev.ctrlKey || ev.altKey || ev.metaKey) { + if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) { return; } @@ -601,11 +579,51 @@ function handleShortcut(ev) { document.addEventListener("keypress", handleShortcut); document.addEventListener("keydown", handleShortcut); +function changeSetting(elem) { + if (elem.id === "disable-shortcuts") { + disableShortcuts = elem.checked; + storeValue(elem.id, elem.checked); + } +} + +function onEachLazy(lazyArray, func) { + const arr = Array.prototype.slice.call(lazyArray); + for (const el of arr) { + func(el); + } +} + +function handleBlur(event) { + const parent = document.getElementById("settings-dropdown"); + if (!parent.contains(document.activeElement) && + !parent.contains(event.relatedTarget) + ) { + parent.classList.remove("open"); + } +} + +function generateSettings() { + const settings = document.getElementById("settings-dropdown"); + const settingsButton = settings.querySelector(".settings-icon") + settingsButton.onclick = () => settings.classList.toggle("open"); + settingsButton.onblur = handleBlur; + const settingsMenu = settings.querySelector(".settings-menu"); + settingsMenu.onblur = handleBlur; + onEachLazy( + settingsMenu.querySelectorAll("input"), + el => el.onblur = handleBlur, + ); +} + +generateSettings(); + // loading the theme after the initial load const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); -const theme = localStorage.getItem('clippy-lint-list-theme'); +const theme = loadValue('theme'); if (prefersDark.matches && !theme) { setTheme("coal", false); } else { setTheme(theme, false); } +let disableShortcuts = loadValue('disable-shortcuts') === "true"; +document.getElementById("disable-shortcuts").checked = disableShortcuts; diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css new file mode 100644 index 00000000000..a9485d51104 --- /dev/null +++ b/src/tools/clippy/util/gh-pages/style.css @@ -0,0 +1,398 @@ +blockquote { font-size: 1em; } + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + +.dropdown-menu { + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); +} + +.dropdown-menu .divider { + background-color: var(--theme-popup-border); +} + +.dropdown-menu .checkbox { + display: block; + white-space: nowrap; + margin: 0; +} +.dropdown-menu .checkbox label { + padding: 3px 20px; + width: 100%; +} + +.dropdown-menu .checkbox input { + position: relative; + margin: 0 0.5rem 0; + padding: 0; +} + +.dropdown-menu .checkbox:hover { + background-color: var(--theme-hover); +} + +div.panel div.panel-body button { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +div.panel div.panel-body button:hover { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +div.panel div.panel-body button.open { + filter: brightness(90%); +} + +.dropdown-toggle .badge { + background-color: #777; +} + +.panel-heading { cursor: pointer; } + +.panel-title { display: flex; flex-wrap: wrap;} +.panel-title .label { display: inline-block; } + +.panel-title-name { flex: 1; min-width: 400px;} +.panel-title-name span { vertical-align: bottom; } + +.panel .panel-title-name .anchor { display: none; } +.panel:hover .panel-title-name .anchor { display: inline;} + +.search-control { + margin-top: 15px; +} + +@media (min-width: 992px) { + .search-control { + margin-top: 0; + } +} + +@media (min-width: 405px) { + #upper-filters { + display: flex; + flex-wrap: wrap; + } +} + +@media (max-width: 430px) { + /* Turn the version filter list to the left */ + #version-filter-selector { + right: 0; + left: auto; + } +} + +@media (max-width: 412px) { + #upper-filters, + .panel-body .search-control { + padding-right: 8px; + padding-left: 8px; + } +} + +.label { + padding-top: 0.3em; + padding-bottom: 0.3em; +} + +.label-lint-group { + min-width: 8em; +} +.label-lint-level { + min-width: 4em; +} + +.label-lint-level-allow { + background-color: #5cb85c; +} +.label-lint-level-warn { + background-color: #f0ad4e; +} +.label-lint-level-deny { + background-color: #d9534f; +} +.label-lint-level-none { + background-color: #777777; + opacity: 0.5; +} + +.label-group-deprecated { + opacity: 0.5; +} + +.label-doc-folding { + color: #000; + background-color: #fff; + border: 1px solid var(--theme-popup-border); +} +.label-doc-folding:hover { + background-color: #e6e6e6; +} + +.lint-doc-md > h3 { + border-top: 1px solid var(--theme-popup-border); + padding: 10px 15px; + margin: 0 -15px; + font-size: 18px; +} +.lint-doc-md > h3:first-child { + border-top: none; + padding-top: 0px; +} + +@media (max-width:749px) { + .lint-additional-info-container { + display: flex; + flex-flow: column; + } + .lint-additional-info-item + .lint-additional-info-item { + border-top: 1px solid var(--theme-popup-border); + } +} +@media (min-width:750px) { + .lint-additional-info-container { + display: flex; + flex-flow: row; + } + .lint-additional-info-item + .lint-additional-info-item { + border-left: 1px solid var(--theme-popup-border); + } +} + +.lint-additional-info-item { + display: inline-flex; + min-width: 200px; + flex-grow: 1; + padding: 9px 5px 5px 15px; +} + +.label-applicability { + background-color: #777777; + margin: auto 5px; +} + +.label-version { + background-color: #777777; + margin: auto 5px; + font-family: monospace; +} + +details { + border-radius: 4px; + padding: .5em .5em 0; +} + +code { + white-space: pre !important; +} + +summary { + font-weight: bold; + margin: -.5em -.5em 0; + padding: .5em; + display: revert; +} + +details[open] { + padding: .5em; +} + +/* Expanding the mdBook theme*/ +.light { + --inline-code-bg: #f6f7f6; +} +.rust { + --inline-code-bg: #f6f7f6; +} +.coal { + --inline-code-bg: #1d1f21; +} +.navy { + --inline-code-bg: #1d1f21; +} +.ayu { + --inline-code-bg: #191f26; +} + +#settings-dropdown { + position: absolute; + margin: 0.7em; + z-index: 10; + display: flex; +} + +/* Applying the mdBook theme */ +.settings-icon { + text-align: center; + width: 2em; + height: 2em; + line-height: 2em; + border: solid 1px var(--icons); + border-radius: 5px; + user-select: none; + cursor: pointer; + background: var(--theme-hover); +} +.settings-menu { + display: none; + list-style: none; + border: 1px solid var(--theme-popup-border); + border-radius: 5px; + color: var(--fg); + background: var(--theme-popup-bg); + overflow: hidden; + padding: 9px; + width: 207px; + position: absolute; + top: 28px; +} + +.settings-icon::before { + /* Wheel <https://www.svgrepo.com/svg/384069/settings-cog-gear> */ + content: url('data:image/svg+xml,<svg width="18" height="18" viewBox="0 0 12 12" \ +enable-background="new 0 0 12 12" xmlns="http://www.w3.org/2000/svg">\ +<path d="M10.25,6c0-0.1243286-0.0261841-0.241333-0.0366211-0.362915l1.6077881-1.5545654l\ +-1.25-2.1650391 c0,0-1.2674561,0.3625488-2.1323853,0.6099854c-0.2034912-0.1431885-0.421875\ +-0.2639771-0.6494751-0.3701782L7.25,0h-2.5 c0,0-0.3214111,1.2857666-0.5393066,2.1572876\ +C3.9830933,2.2634888,3.7647095,2.3842773,3.5612183,2.5274658L1.428833,1.9174805 \ +l-1.25,2.1650391c0,0,0.9641113,0.9321899,1.6077881,1.5545654C1.7761841,5.758667,\ +1.75,5.8756714,1.75,6 s0.0261841,0.241333,0.0366211,0.362915L0.178833,7.9174805l1.25,\ +2.1650391l2.1323853-0.6099854 c0.2034912,0.1432495,0.421875,0.2639771,0.6494751,0.3701782\ +L4.75,12h2.5l0.5393066-2.1572876 c0.2276001-0.1062012,0.4459839-0.2269287,0.6494751\ +-0.3701782l2.1323853,0.6099854l1.25-2.1650391L10.2133789,6.362915 C10.2238159,6.241333,\ +10.25,6.1243286,10.25,6z M6,7.5C5.1715698,7.5,4.5,6.8284302,4.5,6S5.1715698,4.5,6,4.5S7.5\ +,5.1715698,7.5,6 S6.8284302,7.5,6,7.5z" fill="black"/></svg>'); + width: 18px; + height: 18px; + display: block; + filter: invert(0.7); + padding-left: 4px; + padding-top: 3px; +} + +.settings-menu * { + font-weight: normal; +} + +.settings-menu label { + cursor: pointer; +} + +#settings-dropdown.open .settings-menu { + display: block; +} + +#theme-choice { + margin-bottom: 10px; + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + border-radius: 5px; + cursor: pointer; + width: 100%; + border-width: 1px; + padding: 5px; +} + +.alert { + color: var(--fg); + background: var(--theme-hover); + border: 1px solid var(--theme-popup-border); +} +.page-header { + border-color: var(--theme-popup-border); +} +.panel-default > .panel-heading { + background: var(--theme-hover); + color: var(--fg); + border: 1px solid var(--theme-popup-border); +} +.panel-default > .panel-heading:hover { + filter: brightness(90%); +} +.list-group-item { + background: 0%; + border: 1px solid var(--theme-popup-border); +} +.panel, pre, hr { + background: var(--bg); + border: 1px solid var(--theme-popup-border); +} + +#version-filter-selector .checkbox { + display: flex; +} + +#version-filter { + min-width: available; +} + +#version-filter li label { + padding-right: 0; + width: 35%; +} + +.version-filter-input { + height: 60%; + width: 30%; + text-align: center; + border: none; + border-bottom: 1px solid #000000; +} + +#filter-label, .filter-clear { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + filter: brightness(95%); +} +#filter-label:hover, .filter-clear:hover { + filter: brightness(90%); +} +.filter-input { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +.filter-input::-webkit-input-placeholder, +.filter-input::-moz-placeholder { + color: var(--searchbar-fg); + opacity: 30%; +} + +.expansion-group { + margin-top: 15px; + padding: 0px 8px; + display: flex; + flex-wrap: nowrap; +} + +@media (min-width: 992px) { + .expansion-group { + margin-top: 0; + padding: 0px 15px; + } +} + +.expansion-control { + width: 50%; +} + +:not(pre) > code { + color: var(--inline-code-color); + background-color: var(--inline-code-bg); +} +html { + scrollbar-color: var(--scrollbar) var(--bg); +} +body { + background: var(--bg); + color: var(--fg); +} diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 7f8080235c8..a559d6f81a2 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -141,6 +141,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-force-clang-based-tests", "needs-git-hash", "needs-llvm-components", + "needs-llvm-zstd", "needs-profiler-support", "needs-relocation-model-pic", "needs-run-enabled", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 1fc24301c85..933913eb47c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1203,6 +1203,107 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> { None } +/// For tests using the `needs-llvm-zstd` directive: +/// - for local LLVM builds, try to find the static zstd library in the llvm-config system libs. +/// - for `download-ci-llvm`, see if `lld` was built with zstd support. +pub fn llvm_has_libzstd(config: &Config) -> bool { + // Strategy 1: works for local builds but not with `download-ci-llvm`. + // + // We check whether `llvm-config` returns the zstd library. Bootstrap's `llvm.libzstd` will only + // ask to statically link it when building LLVM, so we only check if the list of system libs + // contains a path to that static lib, and that it exists. + // + // See compiler/rustc_llvm/build.rs for more details and similar expectations. + fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> { + let llvm_config_path = llvm_bin_dir.join("llvm-config"); + let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?; + assert!(output.status.success(), "running llvm-config --system-libs failed"); + + let libs = String::from_utf8(output.stdout).ok()?; + for lib in libs.split_whitespace() { + if lib.ends_with("libzstd.a") && Path::new(lib).exists() { + return Some(()); + } + } + + None + } + + // Strategy 2: `download-ci-llvm`'s `llvm-config --system-libs` will not return any libs to + // use. + // + // The CI artifacts also don't contain the bootstrap config used to build them: otherwise we + // could have looked at the `llvm.libzstd` config. + // + // We infer whether `LLVM_ENABLE_ZSTD` was used to build LLVM as a byproduct of testing whether + // `lld` supports it. If not, an error will be emitted: "LLVM was not built with + // LLVM_ENABLE_ZSTD or did not find zstd at build time". + #[cfg(unix)] + fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> { + let lld_path = llvm_bin_dir.join("lld"); + if lld_path.exists() { + // We can't call `lld` as-is, it expects to be invoked by a compiler driver using a + // different name. Prepare a temporary symlink to do that. + let lld_symlink_path = llvm_bin_dir.join("ld.lld"); + if !lld_symlink_path.exists() { + std::os::unix::fs::symlink(lld_path, &lld_symlink_path).ok()?; + } + + // Run `lld` with a zstd flag. We expect this command to always error here, we don't + // want to link actual files and don't pass any. + let output = Command::new(&lld_symlink_path) + .arg("--compress-debug-sections=zstd") + .output() + .ok()?; + assert!(!output.status.success()); + + // Look for a specific error caused by LLVM not being built with zstd support. We could + // also look for the "no input files" message, indicating the zstd flag was accepted. + let stderr = String::from_utf8(output.stderr).ok()?; + let zstd_available = !stderr.contains("LLVM was not built with LLVM_ENABLE_ZSTD"); + + // We don't particularly need to clean the link up (so the previous commands could fail + // in theory but won't in practice), but we can try. + std::fs::remove_file(lld_symlink_path).ok()?; + + if zstd_available { + return Some(()); + } + } + + None + } + + #[cfg(not(unix))] + fn is_lld_built_with_zstd(_llvm_bin_dir: &Path) -> Option<()> { + None + } + + if let Some(llvm_bin_dir) = &config.llvm_bin_dir { + // Strategy 1: for local LLVM builds. + if is_zstd_in_config(llvm_bin_dir).is_some() { + return true; + } + + // Strategy 2: for LLVM artifacts built on CI via `download-ci-llvm`. + // + // It doesn't work for cases where the artifacts don't contain the linker, but it's + // best-effort: CI has `llvm.libzstd` and `lld` enabled on the x64 linux artifacts, so it + // will at least work there. + // + // If this can be improved and expanded to less common cases in the future, it should. + if config.target == "x86_64-unknown-linux-gnu" + && config.host == config.target + && is_lld_built_with_zstd(llvm_bin_dir).is_some() + { + return true; + } + } + + // Otherwise, all hope is lost. + false +} + /// Takes a directive of the form "<version1> [- <version2>]", /// returns the numeric representation of <version1> and <version2> as /// tuple: (<version1> as u32, <version2> as u32) diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 8f935d5b744..72b1b9c6d48 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,5 +1,5 @@ use crate::common::{Config, Sanitizer}; -use crate::header::IgnoreDecision; +use crate::header::{llvm_has_libzstd, IgnoreDecision}; pub(super) fn handle_needs( cache: &CachedNeedsConditions, @@ -144,6 +144,11 @@ pub(super) fn handle_needs( condition: cache.symlinks, ignore_reason: "ignored if symlinks are unavailable", }, + Need { + name: "needs-llvm-zstd", + condition: cache.llvm_zstd, + ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { @@ -169,7 +174,7 @@ pub(super) fn handle_needs( } else { return IgnoreDecision::Ignore { reason: if let Some(comment) = comment { - format!("{} ({comment})", need.ignore_reason) + format!("{} ({})", need.ignore_reason, comment.trim()) } else { need.ignore_reason.into() }, @@ -210,6 +215,8 @@ pub(super) struct CachedNeedsConditions { rust_lld: bool, dlltool: bool, symlinks: bool, + /// Whether LLVM built with zstd, for the `needs-llvm-zstd` directive. + llvm_zstd: bool, } impl CachedNeedsConditions { @@ -253,6 +260,7 @@ impl CachedNeedsConditions { .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" }) .exists(), + llvm_zstd: llvm_has_libzstd(&config), dlltool: find_dlltool(&config), symlinks: has_symlinks(), } diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 72448c1180a..fa77ab1e011 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -6,8 +6,10 @@ //! script is to check all relative links in our documentation to make sure they //! actually point to a valid place. //! -//! Currently this doesn't actually do any HTML parsing or anything fancy like -//! that, it just has a simple "regex" to search for `href` and `id` tags. +//! Currently uses a combination of HTML parsing to +//! extract the `href` and `id` attributes, +//! and regex search on the orignal markdown to handle intra-doc links. +//! //! These values are then translated to file URLs if possible and then the //! destination is asserted to exist. //! diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index e12f3f9012f..4b7f3483ff7 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -20,7 +20,7 @@ doctest = false # and no doc tests [dependencies] getrandom = { version = "0.2", features = ["std"] } rand = "0.8" -smallvec = "1.7" +smallvec = { version = "1.7", features = ["drain_filter"] } aes = { version = "0.8.3", features = ["hazmat"] } measureme = "11" ctrlc = "3.2.5" diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index c3f4f4b5d82..1eca86baeaa 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f24a6ba06f4190d8ec4f22d1baa800e64b1900cb +fdf61d499c8a8421ecf98e7924bb87caf43a9938 diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 90bd1103218..56643c6cbe8 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -10,7 +10,7 @@ //! and the relative position of the access; //! - idempotency properties asserted in `perms.rs` (for optimizations) -use std::fmt; +use std::{fmt, mem}; use smallvec::SmallVec; @@ -699,8 +699,7 @@ impl<'tcx> Tree { /// Integration with the BorTag garbage collector impl Tree { pub fn remove_unreachable_tags(&mut self, live_tags: &FxHashSet<BorTag>) { - let root_is_needed = self.keep_only_needed(self.root, live_tags); // root can't be removed - assert!(root_is_needed); + self.remove_useless_children(self.root, live_tags); // Right after the GC runs is a good moment to check if we can // merge some adjacent ranges that were made equal by the removal of some // tags (this does not necessarily mean that they have identical internal representations, @@ -708,9 +707,16 @@ impl Tree { self.rperms.merge_adjacent_thorough(); } + /// Checks if a node is useless and should be GC'ed. + /// A node is useless if it has no children and also the tag is no longer live. + fn is_useless(&self, idx: UniIndex, live: &FxHashSet<BorTag>) -> bool { + let node = self.nodes.get(idx).unwrap(); + node.children.is_empty() && !live.contains(&node.tag) + } + /// Traverses the entire tree looking for useless tags. - /// Returns true iff the tag it was called on is still live or has live children, - /// and removes from the tree all tags that have no live children. + /// Removes from the tree all useless child nodes of root. + /// It will not delete the root itself. /// /// NOTE: This leaves in the middle of the tree tags that are unreachable but have /// reachable children. There is a potential for compacting the tree by reassigning @@ -721,42 +727,60 @@ impl Tree { /// `child: Reserved`. This tree can exist. If we blindly delete `parent` and reassign /// `child` to be a direct child of `root` then Writes to `child` are now permitted /// whereas they were not when `parent` was still there. - fn keep_only_needed(&mut self, idx: UniIndex, live: &FxHashSet<BorTag>) -> bool { - let node = self.nodes.get(idx).unwrap(); - // FIXME: this function does a lot of cloning, a 2-pass approach is possibly - // more efficient. It could consist of - // 1. traverse the Tree, collect all useless tags in a Vec - // 2. traverse the Vec, remove all tags previously selected - // Bench it. - let children: SmallVec<_> = node - .children - .clone() - .into_iter() - .filter(|child| self.keep_only_needed(*child, live)) - .collect(); - let no_children = children.is_empty(); - let node = self.nodes.get_mut(idx).unwrap(); - node.children = children; - if !live.contains(&node.tag) && no_children { - // All of the children and this node are unreachable, delete this tag - // from the tree (the children have already been deleted by recursive - // calls). - // Due to the API of UniMap we must absolutely call - // `UniValMap::remove` for the key of this tag on *all* maps that used it - // (which are `self.nodes` and every range of `self.rperms`) - // before we can safely apply `UniValMap::forget` to truly remove - // the tag from the mapping. - let tag = node.tag; - self.nodes.remove(idx); - for (_perms_range, perms) in self.rperms.iter_mut_all() { - perms.remove(idx); + fn remove_useless_children(&mut self, root: UniIndex, live: &FxHashSet<BorTag>) { + // To avoid stack overflows, we roll our own stack. + // Each element in the stack consists of the current tag, and the number of the + // next child to be processed. + + // The other functions are written using the `TreeVisitorStack`, but that does not work here + // since we need to 1) do a post-traversal and 2) remove nodes from the tree. + // Since we do a post-traversal (by deleting nodes only after handling all children), + // we also need to be a bit smarter than "pop node, push all children." + let mut stack = vec![(root, 0)]; + while let Some((tag, nth_child)) = stack.last_mut() { + let node = self.nodes.get(*tag).unwrap(); + if *nth_child < node.children.len() { + // Visit the child by pushing it to the stack. + // Also increase `nth_child` so that when we come back to the `tag` node, we + // look at the next child. + let next_child = node.children[*nth_child]; + *nth_child += 1; + stack.push((next_child, 0)); + continue; + } else { + // We have processed all children of `node`, so now it is time to process `node` itself. + // First, get the current children of `node`. To appease the borrow checker, + // we have to temporarily move the list out of the node, and then put the + // list of remaining children back in. + let mut children_of_node = + mem::take(&mut self.nodes.get_mut(*tag).unwrap().children); + // Remove all useless children, and save them for later. + // The closure needs `&self` and the loop below needs `&mut self`, so we need to `collect` + // in to a temporary list. + let to_remove: Vec<_> = + children_of_node.drain_filter(|x| self.is_useless(*x, live)).collect(); + // Put back the now-filtered vector. + self.nodes.get_mut(*tag).unwrap().children = children_of_node; + // Now, all that is left is unregistering the children saved in `to_remove`. + for idx in to_remove { + // Note: In the rest of this comment, "this node" refers to `idx`. + // This node has no more children (if there were any, they have already been removed). + // It is also unreachable as determined by the GC, so we can remove it everywhere. + // Due to the API of UniMap we must make sure to call + // `UniValMap::remove` for the key of this node on *all* maps that used it + // (which are `self.nodes` and every range of `self.rperms`) + // before we can safely apply `UniKeyMap::remove` to truly remove + // this tag from the `tag_mapping`. + let node = self.nodes.remove(idx).unwrap(); + for (_perms_range, perms) in self.rperms.iter_mut_all() { + perms.remove(idx); + } + self.tag_mapping.remove(&node.tag); + } + // We are done, the parent can continue. + stack.pop(); + continue; } - self.tag_mapping.remove(&tag); - // The tag has been deleted, inform the caller - false - } else { - // The tag is still live or has live children, it must be kept - true } } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index f45b2d9e00a..92bae6203b3 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -12,7 +12,7 @@ #![allow(dead_code)] -use std::hash::Hash; +use std::{hash::Hash, mem}; use rustc_data_structures::fx::FxHashMap; @@ -187,13 +187,16 @@ impl<V> UniValMap<V> { self.data.get_mut(idx.idx as usize).and_then(Option::as_mut) } - /// Delete any value associated with this index. Ok even if the index - /// has no associated value. - pub fn remove(&mut self, idx: UniIndex) { + /// Delete any value associated with this index. + /// Returns None if the value was not present, otherwise + /// returns the previously stored value. + pub fn remove(&mut self, idx: UniIndex) -> Option<V> { if idx.idx as usize >= self.data.len() { - return; + return None; } - self.data[idx.idx as usize] = None; + let mut res = None; + mem::swap(&mut res, &mut self.data[idx.idx as usize]); + res } } diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 9df0d95f1f2..6fd207c92b9 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -617,9 +617,10 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // the *value* (including the associated provenance if this is an AtomicPtr) at this location. // Only metadata on the location itself is used. let scalar = this.allow_data_races_ref(move |this| this.read_scalar(place))?; - this.buffered_atomic_read(place, atomic, scalar, || { + let buffered_scalar = this.buffered_atomic_read(place, atomic, scalar, || { this.validate_atomic_load(place, atomic) - }) + })?; + Ok(buffered_scalar.ok_or_else(|| err_ub!(InvalidUninitBytes(None)))?) } /// Perform an atomic write operation at the memory location. @@ -632,14 +633,14 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); this.atomic_access_check(dest, AtomicAccessType::Store)?; + // Read the previous value so we can put it in the store buffer later. + // The program didn't actually do a read, so suppress the memory access hooks. + // This is also a very special exception where we just ignore an error -- if this read + // was UB e.g. because the memory is uninitialized, we don't want to know! + let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; - // FIXME: it's not possible to get the value before write_scalar. A read_scalar will cause - // side effects from a read the program did not perform. So we have to initialise - // the store buffer with the value currently being written - // ONCE this is fixed please remove the hack in buffered_atomic_write() in weak_memory.rs - // https://github.com/rust-lang/miri/issues/2164 - this.buffered_atomic_write(val, dest, atomic, val) + this.buffered_atomic_write(val, dest, atomic, old_val) } /// Perform an atomic RMW operation on a memory location. @@ -768,7 +769,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // in the modification order. // Since `old` is only a value and not the store element, we need to separately // find it in our store buffer and perform load_impl on it. - this.perform_read_on_buffered_latest(place, fail, old.to_scalar())?; + this.perform_read_on_buffered_latest(place, fail)?; } // Return the old value. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index f72591f0c4b..a4d3e3f7af3 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -1157,7 +1157,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } #[inline] - fn get_thread_name<'c>(&'c self, thread: ThreadId) -> Option<&[u8]> + fn get_thread_name<'c>(&'c self, thread: ThreadId) -> Option<&'c [u8]> where 'tcx: 'c, { diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index 6f4171584a8..0605b744e6a 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -39,11 +39,10 @@ //! to attach store buffers to atomic objects. However, Rust follows LLVM in that it only has //! 'atomic accesses'. Therefore Miri cannot know when and where atomic 'objects' are being //! created or destroyed, to manage its store buffers. Instead, we hence lazily create an -//! atomic object on the first atomic access to a given region, and we destroy that object -//! on the next non-atomic or imperfectly overlapping atomic access to that region. +//! atomic object on the first atomic write to a given region, and we destroy that object +//! on the next non-atomic or imperfectly overlapping atomic write to that region. //! These lazy (de)allocations happen in memory_accessed() on non-atomic accesses, and -//! get_or_create_store_buffer() on atomic accesses. This mostly works well, but it does -//! lead to some issues (<https://github.com/rust-lang/miri/issues/2164>). +//! get_or_create_store_buffer_mut() on atomic writes. //! //! One consequence of this difference is that safe/sound Rust allows for more operations on atomic locations //! than the C++20 atomic API was intended to allow, such as non-atomically accessing @@ -144,11 +143,9 @@ struct StoreElement { /// The timestamp of the storing thread when it performed the store timestamp: VTimestamp, - /// The value of this store - // FIXME: this means the store must be fully initialized; - // we will have to change this if we want to support atomics on - // (partially) uninitialized data. - val: Scalar, + /// The value of this store. `None` means uninitialized. + // FIXME: Currently, we cannot represent partial initialization. + val: Option<Scalar>, /// Metadata about loads from this store element, /// behind a RefCell to keep load op take &self @@ -170,7 +167,7 @@ impl StoreBufferAlloc { /// When a non-atomic access happens on a location that has been atomically accessed /// before without data race, we can determine that the non-atomic access fully happens - /// after all the prior atomic accesses so the location no longer needs to exhibit + /// after all the prior atomic writes so the location no longer needs to exhibit /// any weak memory behaviours until further atomic accesses. pub fn memory_accessed(&self, range: AllocRange, global: &DataRaceState) { if !global.ongoing_action_data_race_free() { @@ -192,37 +189,29 @@ impl StoreBufferAlloc { } } - /// Gets a store buffer associated with an atomic object in this allocation, - /// or creates one with the specified initial value if no atomic object exists yet. - fn get_or_create_store_buffer<'tcx>( + /// Gets a store buffer associated with an atomic object in this allocation. + /// Returns `None` if there is no store buffer. + fn get_store_buffer<'tcx>( &self, range: AllocRange, - init: Scalar, - ) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> { + ) -> InterpResult<'tcx, Option<Ref<'_, StoreBuffer>>> { let access_type = self.store_buffers.borrow().access_type(range); let pos = match access_type { AccessType::PerfectlyOverlapping(pos) => pos, - AccessType::Empty(pos) => { - let mut buffers = self.store_buffers.borrow_mut(); - buffers.insert_at_pos(pos, range, StoreBuffer::new(init)); - pos - } - AccessType::ImperfectlyOverlapping(pos_range) => { - // Once we reach here we would've already checked that this access is not racy. - let mut buffers = self.store_buffers.borrow_mut(); - buffers.remove_pos_range(pos_range.clone()); - buffers.insert_at_pos(pos_range.start, range, StoreBuffer::new(init)); - pos_range.start - } + // If there is nothing here yet, that means there wasn't an atomic write yet so + // we can't return anything outdated. + _ => return Ok(None), }; - Ok(Ref::map(self.store_buffers.borrow(), |buffer| &buffer[pos])) + let store_buffer = Ref::map(self.store_buffers.borrow(), |buffer| &buffer[pos]); + Ok(Some(store_buffer)) } - /// Gets a mutable store buffer associated with an atomic object in this allocation + /// Gets a mutable store buffer associated with an atomic object in this allocation, + /// or creates one with the specified initial value if no atomic object exists yet. fn get_or_create_store_buffer_mut<'tcx>( &mut self, range: AllocRange, - init: Scalar, + init: Option<Scalar>, ) -> InterpResult<'tcx, &mut StoreBuffer> { let buffers = self.store_buffers.get_mut(); let access_type = buffers.access_type(range); @@ -244,10 +233,8 @@ impl StoreBufferAlloc { } impl<'tcx> StoreBuffer { - fn new(init: Scalar) -> Self { + fn new(init: Option<Scalar>) -> Self { let mut buffer = VecDeque::new(); - buffer.reserve(STORE_BUFFER_LIMIT); - let mut ret = Self { buffer }; let store_elem = StoreElement { // The thread index and timestamp of the initialisation write // are never meaningfully used, so it's fine to leave them as 0 @@ -257,11 +244,11 @@ impl<'tcx> StoreBuffer { is_seqcst: false, load_info: RefCell::new(LoadInfo::default()), }; - ret.buffer.push_back(store_elem); - ret + buffer.push_back(store_elem); + Self { buffer } } - /// Reads from the last store in modification order + /// Reads from the last store in modification order, if any. fn read_from_last_store( &self, global: &DataRaceState, @@ -282,7 +269,7 @@ impl<'tcx> StoreBuffer { is_seqcst: bool, rng: &mut (impl rand::Rng + ?Sized), validate: impl FnOnce() -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, (Scalar, LoadRecency)> { + ) -> InterpResult<'tcx, (Option<Scalar>, LoadRecency)> { // Having a live borrow to store_buffer while calling validate_atomic_load is fine // because the race detector doesn't touch store_buffer @@ -419,15 +406,15 @@ impl<'tcx> StoreBuffer { // In the language provided in the paper, an atomic store takes the value from a // non-atomic memory location. // But we already have the immediate value here so we don't need to do the memory - // access - val, + // access. + val: Some(val), is_seqcst, load_info: RefCell::new(LoadInfo::default()), }; - self.buffer.push_back(store_elem); - if self.buffer.len() > STORE_BUFFER_LIMIT { + if self.buffer.len() >= STORE_BUFFER_LIMIT { self.buffer.pop_front(); } + self.buffer.push_back(store_elem); if is_seqcst { // Every store that happens before this needs to be marked as SC // so that in a later SC load, only the last SC store (i.e. this one) or stores that @@ -450,7 +437,12 @@ impl StoreElement { /// buffer regardless of subsequent loads by the same thread; if the earliest load of another /// thread doesn't happen before the current one, then no subsequent load by the other thread /// can happen before the current one. - fn load_impl(&self, index: VectorIdx, clocks: &ThreadClockSet, is_seqcst: bool) -> Scalar { + fn load_impl( + &self, + index: VectorIdx, + clocks: &ThreadClockSet, + is_seqcst: bool, + ) -> Option<Scalar> { let mut load_info = self.load_info.borrow_mut(); load_info.sc_loaded |= is_seqcst; let _ = load_info.timestamps.try_insert(index, clocks.clock[index]); @@ -479,7 +471,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { global.sc_write(threads); } let range = alloc_range(base_offset, place.layout.size); - let buffer = alloc_buffers.get_or_create_store_buffer_mut(range, init)?; + let buffer = alloc_buffers.get_or_create_store_buffer_mut(range, Some(init))?; buffer.read_from_last_store(global, threads, atomic == AtomicRwOrd::SeqCst); buffer.buffered_write(new_val, global, threads, atomic == AtomicRwOrd::SeqCst)?; } @@ -492,47 +484,55 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { atomic: AtomicReadOrd, latest_in_mo: Scalar, validate: impl FnOnce() -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, Option<Scalar>> { let this = self.eval_context_ref(); - if let Some(global) = &this.machine.data_race { - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; - if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { - if atomic == AtomicReadOrd::SeqCst { - global.sc_read(&this.machine.threads); - } - let mut rng = this.machine.rng.borrow_mut(); - let buffer = alloc_buffers.get_or_create_store_buffer( - alloc_range(base_offset, place.layout.size), - latest_in_mo, - )?; - let (loaded, recency) = buffer.buffered_read( - global, - &this.machine.threads, - atomic == AtomicReadOrd::SeqCst, - &mut *rng, - validate, - )?; - if global.track_outdated_loads && recency == LoadRecency::Outdated { - this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad { - ptr: place.ptr(), - }); + 'fallback: { + if let Some(global) = &this.machine.data_race { + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; + if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { + if atomic == AtomicReadOrd::SeqCst { + global.sc_read(&this.machine.threads); + } + let mut rng = this.machine.rng.borrow_mut(); + let Some(buffer) = alloc_buffers + .get_store_buffer(alloc_range(base_offset, place.layout.size))? + else { + // No old writes available, fall back to base case. + break 'fallback; + }; + let (loaded, recency) = buffer.buffered_read( + global, + &this.machine.threads, + atomic == AtomicReadOrd::SeqCst, + &mut *rng, + validate, + )?; + if global.track_outdated_loads && recency == LoadRecency::Outdated { + this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad { + ptr: place.ptr(), + }); + } + + return Ok(loaded); } - - return Ok(loaded); } } // Race detector or weak memory disabled, simply read the latest value validate()?; - Ok(latest_in_mo) + Ok(Some(latest_in_mo)) } + /// Add the given write to the store buffer. (Does not change machine memory.) + /// + /// `init` says with which value to initialize the store buffer in case there wasn't a store + /// buffer for this memory range before. fn buffered_atomic_write( &mut self, val: Scalar, dest: &MPlaceTy<'tcx>, atomic: AtomicWriteOrd, - init: Scalar, + init: Option<Scalar>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr(), 0)?; @@ -545,23 +545,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { global.sc_write(threads); } - // UGLY HACK: in write_scalar_atomic() we don't know the value before our write, - // so init == val always. If the buffer is fresh then we would've duplicated an entry, - // so we need to remove it. - // See https://github.com/rust-lang/miri/issues/2164 - let was_empty = matches!( - alloc_buffers - .store_buffers - .borrow() - .access_type(alloc_range(base_offset, dest.layout.size)), - AccessType::Empty(_) - ); let buffer = alloc_buffers .get_or_create_store_buffer_mut(alloc_range(base_offset, dest.layout.size), init)?; - if was_empty { - buffer.buffer.pop_front(); - } - buffer.buffered_write(val, global, threads, atomic == AtomicWriteOrd::SeqCst)?; } @@ -576,7 +561,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &self, place: &MPlaceTy<'tcx>, atomic: AtomicReadOrd, - init: Scalar, ) -> InterpResult<'tcx> { let this = self.eval_context_ref(); @@ -587,8 +571,12 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let size = place.layout.size; let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { - let buffer = alloc_buffers - .get_or_create_store_buffer(alloc_range(base_offset, size), init)?; + let Some(buffer) = + alloc_buffers.get_store_buffer(alloc_range(base_offset, size))? + else { + // No store buffer, nothing to do. + return Ok(()); + }; buffer.read_from_last_store( global, &this.machine.threads, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index a7493d48d6a..264b7b269de 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -947,15 +947,47 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } #[inline(always)] - fn enforce_abi(_ecx: &MiriInterpCx<'tcx>) -> bool { - true - } - - #[inline(always)] fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'tcx>) -> bool { !ecx.tcx.sess.overflow_checks() } + fn check_fn_target_features( + ecx: &MiriInterpCx<'tcx>, + instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx> { + let attrs = ecx.tcx.codegen_fn_attrs(instance.def_id()); + if attrs + .target_features + .iter() + .any(|feature| !ecx.tcx.sess.target_features.contains(&feature.name)) + { + let unavailable = attrs + .target_features + .iter() + .filter(|&feature| { + !feature.implied && !ecx.tcx.sess.target_features.contains(&feature.name) + }) + .fold(String::new(), |mut s, feature| { + if !s.is_empty() { + s.push_str(", "); + } + s.push_str(feature.name.as_str()); + s + }); + let msg = format!( + "calling a function that requires unavailable target features: {unavailable}" + ); + // On WASM, this is not UB, but instead gets rejected during validation of the module + // (see #84988). + if ecx.tcx.sess.target.is_like_wasm { + throw_machine_stop!(TerminationInfo::Abort(msg)); + } else { + throw_ub_format!("{msg}"); + } + } + Ok(()) + } + #[inline(always)] fn find_mir_or_eval_fn( ecx: &mut MiriInterpCx<'tcx>, @@ -1060,6 +1092,10 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.generate_nan(inputs) } + fn ub_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { + Ok(ecx.tcx.sess.ub_checks()) + } + fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'tcx>, def_id: DefId, diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 80f4b89bf34..e00758bb98d 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1204,14 +1204,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "freebsd" => { - this.write_int(ino, &this.project_field_named(&entry_place, "d_fileno")?)?; - // `d_off` only exists on FreeBSD 12+, but we support v11 as well. - // `libc` uses a build script to determine which version of the API to use, - // and cross-builds always end up using v11. - // To support both v11 and v12+, we dynamically check whether the field exists. - if this.projectable_has_field(&entry_place, "d_off") { - this.write_int(0, &this.project_field_named(&entry_place, "d_off")?)?; - } + #[rustfmt::skip] + this.write_int_fields_named( + &[ + ("d_fileno", ino.into()), + ("d_off", 0), + ], + &entry_place, + )?; } _ => unreachable!(), } diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index c1117e4d811..305e59fa0cd 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -15,6 +15,7 @@ mod aesni; mod avx; mod avx2; mod bmi; +mod sha; mod sse; mod sse2; mod sse3; @@ -105,6 +106,11 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this, link_name, abi, args, dest, ); } + name if name.starts_with("sha") => { + return sha::EvalContextExt::emulate_x86_sha_intrinsic( + this, link_name, abi, args, dest, + ); + } name if name.starts_with("sse.") => { return sse::EvalContextExt::emulate_x86_sse_intrinsic( this, link_name, abi, args, dest, diff --git a/src/tools/miri/src/shims/x86/sha.rs b/src/tools/miri/src/shims/x86/sha.rs new file mode 100644 index 00000000000..e9cc28be34c --- /dev/null +++ b/src/tools/miri/src/shims/x86/sha.rs @@ -0,0 +1,221 @@ +//! Implements sha256 SIMD instructions of x86 targets +//! +//! The functions that actually compute SHA256 were copied from [RustCrypto's sha256 module]. +//! +//! [RustCrypto's sha256 module]: https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/soft.rs + +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use crate::*; + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + fn emulate_x86_sha_intrinsic( + &mut self, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx, EmulateItemResult> { + let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sha")?; + // Prefix should have already been checked. + let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sha").unwrap(); + + fn read<'c>(this: &mut MiriInterpCx<'c>, reg: &MPlaceTy<'c>) -> InterpResult<'c, [u32; 4]> { + let mut res = [0; 4]; + // We reverse the order because x86 is little endian but the copied implementation uses + // big endian. + for (i, dst) in res.iter_mut().rev().enumerate() { + let projected = &this.project_index(reg, i.try_into().unwrap())?; + *dst = this.read_scalar(projected)?.to_u32()? + } + Ok(res) + } + + fn write<'c>( + this: &mut MiriInterpCx<'c>, + dest: &MPlaceTy<'c>, + val: [u32; 4], + ) -> InterpResult<'c, ()> { + // We reverse the order because x86 is little endian but the copied implementation uses + // big endian. + for (i, part) in val.into_iter().rev().enumerate() { + let projected = &this.project_index(dest, i.try_into().unwrap())?; + this.write_scalar(Scalar::from_u32(part), projected)?; + } + Ok(()) + } + + match unprefixed_name { + // Used to implement the _mm_sha256rnds2_epu32 function. + "256rnds2" => { + let [a, b, k] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (k_reg, k_len) = this.operand_to_simd(k)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(k_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + let k = read(this, &k_reg)?; + + let result = sha256_digest_round_x2(a, b, k); + write(this, &dest, result)?; + } + // Used to implement the _mm_sha256msg1_epu32 function. + "256msg1" => { + let [a, b] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + + let result = sha256msg1(a, b); + write(this, &dest, result)?; + } + // Used to implement the _mm_sha256msg2_epu32 function. + "256msg2" => { + let [a, b] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + + let (a_reg, a_len) = this.operand_to_simd(a)?; + let (b_reg, b_len) = this.operand_to_simd(b)?; + let (dest, dest_len) = this.mplace_to_simd(dest)?; + + assert_eq!(a_len, 4); + assert_eq!(b_len, 4); + assert_eq!(dest_len, 4); + + let a = read(this, &a_reg)?; + let b = read(this, &b_reg)?; + + let result = sha256msg2(a, b); + write(this, &dest, result)?; + } + _ => return Ok(EmulateItemResult::NotSupported), + } + Ok(EmulateItemResult::NeedsReturn) + } +} + +#[inline(always)] +fn shr(v: [u32; 4], o: u32) -> [u32; 4] { + [v[0] >> o, v[1] >> o, v[2] >> o, v[3] >> o] +} + +#[inline(always)] +fn shl(v: [u32; 4], o: u32) -> [u32; 4] { + [v[0] << o, v[1] << o, v[2] << o, v[3] << o] +} + +#[inline(always)] +fn or(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [a[0] | b[0], a[1] | b[1], a[2] | b[2], a[3] | b[3]] +} + +#[inline(always)] +fn xor(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]] +} + +#[inline(always)] +fn add(a: [u32; 4], b: [u32; 4]) -> [u32; 4] { + [ + a[0].wrapping_add(b[0]), + a[1].wrapping_add(b[1]), + a[2].wrapping_add(b[2]), + a[3].wrapping_add(b[3]), + ] +} + +fn sha256load(v2: [u32; 4], v3: [u32; 4]) -> [u32; 4] { + [v3[3], v2[0], v2[1], v2[2]] +} + +fn sha256_digest_round_x2(cdgh: [u32; 4], abef: [u32; 4], wk: [u32; 4]) -> [u32; 4] { + macro_rules! big_sigma0 { + ($a:expr) => { + ($a.rotate_right(2) ^ $a.rotate_right(13) ^ $a.rotate_right(22)) + }; + } + macro_rules! big_sigma1 { + ($a:expr) => { + ($a.rotate_right(6) ^ $a.rotate_right(11) ^ $a.rotate_right(25)) + }; + } + macro_rules! bool3ary_202 { + ($a:expr, $b:expr, $c:expr) => { + $c ^ ($a & ($b ^ $c)) + }; + } // Choose, MD5F, SHA1C + macro_rules! bool3ary_232 { + ($a:expr, $b:expr, $c:expr) => { + ($a & $b) ^ ($a & $c) ^ ($b & $c) + }; + } // Majority, SHA1M + + let [_, _, wk1, wk0] = wk; + let [a0, b0, e0, f0] = abef; + let [c0, d0, g0, h0] = cdgh; + + // a round + let x0 = + big_sigma1!(e0).wrapping_add(bool3ary_202!(e0, f0, g0)).wrapping_add(wk0).wrapping_add(h0); + let y0 = big_sigma0!(a0).wrapping_add(bool3ary_232!(a0, b0, c0)); + let (a1, b1, c1, d1, e1, f1, g1, h1) = + (x0.wrapping_add(y0), a0, b0, c0, x0.wrapping_add(d0), e0, f0, g0); + + // a round + let x1 = + big_sigma1!(e1).wrapping_add(bool3ary_202!(e1, f1, g1)).wrapping_add(wk1).wrapping_add(h1); + let y1 = big_sigma0!(a1).wrapping_add(bool3ary_232!(a1, b1, c1)); + let (a2, b2, _, _, e2, f2, _, _) = + (x1.wrapping_add(y1), a1, b1, c1, x1.wrapping_add(d1), e1, f1, g1); + + [a2, b2, e2, f2] +} + +fn sha256msg1(v0: [u32; 4], v1: [u32; 4]) -> [u32; 4] { + // sigma 0 on vectors + #[inline] + fn sigma0x4(x: [u32; 4]) -> [u32; 4] { + let t1 = or(shr(x, 7), shl(x, 25)); + let t2 = or(shr(x, 18), shl(x, 14)); + let t3 = shr(x, 3); + xor(xor(t1, t2), t3) + } + + add(v0, sigma0x4(sha256load(v0, v1))) +} + +fn sha256msg2(v4: [u32; 4], v3: [u32; 4]) -> [u32; 4] { + macro_rules! sigma1 { + ($a:expr) => { + $a.rotate_right(17) ^ $a.rotate_right(19) ^ ($a >> 10) + }; + } + + let [x3, x2, x1, x0] = v4; + let [w15, w14, _, _] = v3; + + let w16 = x0.wrapping_add(sigma1!(w14)); + let w17 = x1.wrapping_add(sigma1!(w15)); + let w18 = x2.wrapping_add(sigma1!(w16)); + let w19 = x3.wrapping_add(sigma1!(w17)); + + [w19, w18, w17, w16] +} diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index e94bef52952..bbead878223 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linux-raw-sys" diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs index 19c62913b4c..bbf069b7a2d 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs @@ -4,7 +4,9 @@ //@normalize-stderr-test: "using [A-Za-z]+ heap deallocation operation" -> "using PLATFORM heap deallocation operation" //@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "libc::free\([^()]*\)|unsafe \{ HeapFree\([^}]*\};" -> "FREE();" +//@normalize-stderr-test: "unsafe \{ libc::free\([^()]*\) \}|unsafe \{ HeapFree\([^}]*\};" -> "FREE();" +//@normalize-stderr-test: "alloc::[A-Za-z]+::" -> "alloc::PLATFORM::" +//@normalize-stderr-test: "alloc/[A-Za-z]+.rs" -> "alloc/PLATFORM.rs" #![feature(allocator_api, slice_ptr_get)] @@ -13,7 +15,5 @@ use std::alloc::{Allocator, Global, Layout, System}; fn main() { let l = Layout::from_size_align(1, 1).unwrap(); let ptr = Global.allocate(l).unwrap().as_non_null_ptr(); - unsafe { - System.deallocate(ptr, l); - } + unsafe { System.deallocate(ptr, l) }; } diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr index 7006b96ee1e..287a1f1a3e3 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation - --> RUSTLIB/std/src/sys/pal/PLATFORM/alloc.rs:LL:CC + --> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC | LL | FREE(); | ^ deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation @@ -7,12 +7,12 @@ LL | FREE(); = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::alloc::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/pal/PLATFORM/alloc.rs:LL:CC + = note: inside `std::sys::alloc::PLATFORM::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC = note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC note: inside `main` --> $DIR/global_system_mixup.rs:LL:CC | -LL | System.deallocate(ptr, l); +LL | unsafe { System.deallocate(ptr, l) }; | ^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs new file mode 100644 index 00000000000..aed5cb11258 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.rs @@ -0,0 +1,19 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +//@[tree]error-in-other-file: /deallocation .* is forbidden/ +use std::alloc::{alloc, dealloc, Layout}; + +// `x` is strongly protected but covers zero bytes. +// Let's see if deallocating the allocation x points to is UB: +// in TB, it is UB, but in SB it is not. +fn test(_x: &mut (), ptr: *mut u8, l: Layout) { + unsafe { dealloc(ptr, l) }; +} + +fn main() { + let l = Layout::from_size_align(1, 1).unwrap(); + let ptr = unsafe { alloc(l) }; + unsafe { test(&mut *ptr.cast::<()>(), ptr, l) }; + // In SB the test would pass if it weren't for this line. + unsafe { std::hint::unreachable_unchecked() }; //~[stack] ERROR: unreachable +} diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr new file mode 100644 index 00000000000..672682ff294 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.stack.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: entering unreachable code + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { std::hint::unreachable_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/zero-sized-protected.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr new file mode 100644 index 00000000000..ef981038e55 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/zero-sized-protected.tree.stderr @@ -0,0 +1,36 @@ +error: Undefined Behavior: deallocation through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden + --> RUSTLIB/alloc/src/alloc.rs:LL:CC + | +LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocation through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the allocation of the accessed tag <TAG> (root of the allocation) also contains the strongly protected tag <TAG> + = help: the strongly protected tag <TAG> disallows deallocations +help: the accessed tag <TAG> was created here + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | let ptr = unsafe { alloc(l) }; + | ^^^^^^^^ +help: the strongly protected tag <TAG> was created here, in the initial state Reserved + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | fn test(_x: &mut (), ptr: *mut u8, l: Layout) { + | ^^ + = note: BACKTRACE (of the first span): + = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC +note: inside `test` + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { dealloc(ptr, l) }; + | ^^^^^^^^^^^^^^^ +note: inside `main` + --> $DIR/zero-sized-protected.rs:LL:CC + | +LL | unsafe { test(&mut *ptr.cast::<()>(), ptr, l) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr index 42beed4ecde..a11a2b95689 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind1.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind1.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/exported_symbol_bad_unwind1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index 112a9687837..12425cc4892 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index 112a9687837..12425cc4892 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr index bc3e4858716..f9e299bf5d2 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr index a2fa4c1d590..83efc9974e8 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/return_pointer_on_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/return_pointer_on_unwind.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr index 8dd76edafea..67fd60e572e 100644 --- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr +++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: aborted execution: attempted to instantiate uninhabited type `!` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr index 55f66a275b6..f89a1fc4bbb 100644 --- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr +++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: aborted execution: attempted to zero-initialize type `fn()`, which is invalid note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr index 230e8337c7c..c08fe5153b1 100644 --- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/bad_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: Undefined Behavior: unwinding past a stack frame that does not allow unwinding --> $DIR/bad_unwind.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 5829c1897bb..0395fe418d9 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC: first note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/double_panic.rs:LL:CC: second stack backtrace: diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index d4abf19cd1e..6c7cac23bec 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort1.rs:LL:CC: panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index 507f17abf4e..1eda5449d1b 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort2.rs:LL:CC: 42-panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index a5d8b4d2eeb..5c7c5e17bee 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort3.rs:LL:CC: panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 62fbbf942cb..c8104f570f6 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic_abort4.rs:LL:CC: 42-panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution --> RUSTLIB/panic_abort/src/lib.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index a5fa0b3e07a..6384689c563 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -3,7 +3,7 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 547d550d3d0..fd67bdf4a90 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a function that cannot unwind stack backtrace: diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs new file mode 100644 index 00000000000..54bea6c6908 --- /dev/null +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs @@ -0,0 +1,43 @@ +//@compile-flags: -Zmiri-ignore-leaks -Zmiri-preemption-rate=0 + +// Tests showing weak memory behaviours are exhibited. All tests +// return true when the desired behaviour is seen. +// This is scheduler and pseudo-RNG dependent, so each test is +// run multiple times until one try returns true. +// Spurious failure is possible, if you are really unlucky with +// the RNG and always read the latest value from the store buffer. +#![feature(new_uninit)] + +use std::sync::atomic::*; +use std::thread::spawn; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +struct EvilSend<T>(pub T); + +unsafe impl<T> Send for EvilSend<T> {} +unsafe impl<T> Sync for EvilSend<T> {} + +// We can't create static items because we need to run each test multiple times. +fn static_uninit_atomic() -> &'static AtomicUsize { + unsafe { Box::leak(Box::new_uninit()).assume_init_ref() } +} + +fn relaxed() { + let x = static_uninit_atomic(); + let j1 = spawn(move || { + x.store(1, Ordering::Relaxed); + }); + + let j2 = spawn(move || x.load(Ordering::Relaxed)); //~ERROR: using uninitialized data + + j1.join().unwrap(); + j2.join().unwrap(); +} + +pub fn main() { + // If we try often enough, we should hit UB. + for _ in 0..100 { + relaxed(); + } +} diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr b/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr new file mode 100644 index 00000000000..9aa5bc2fa76 --- /dev/null +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/weak_uninit.rs:LL:CC + | +LL | let j2 = spawn(move || x.load(Ordering::Relaxed)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE on thread `unnamed-ID`: + = note: inside closure at $DIR/weak_uninit.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr index 5b309ed09bb..319a10febb3 100644 --- a/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr +++ b/src/tools/miri/tests/panic/alloc_error_handler_hook.stderr @@ -1,5 +1,5 @@ thread 'main' panicked at $DIR/alloc_error_handler_hook.rs:LL:CC: alloc error hook called note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect yes we are unwinding! diff --git a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr index 3d5457799f6..2cdff03f10f 100644 --- a/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr +++ b/src/tools/miri/tests/panic/alloc_error_handler_panic.stderr @@ -1,5 +1,5 @@ thread 'main' panicked at RUSTLIB/std/src/alloc.rs:LL:CC: memory allocation of 4 bytes failed note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect yes we are unwinding! diff --git a/src/tools/miri/tests/panic/div-by-zero-2.stderr b/src/tools/miri/tests/panic/div-by-zero-2.stderr index f0b84ea6fd6..ed394f76b0e 100644 --- a/src/tools/miri/tests/panic/div-by-zero-2.stderr +++ b/src/tools/miri/tests/panic/div-by-zero-2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/div-by-zero-2.rs:LL:CC: attempt to divide by zero note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr index f77f6f01119..6733f2e42c1 100644 --- a/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr +++ b/src/tools/miri/tests/panic/function_calls/exported_symbol_good_unwind.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: explicit panic thread 'main' panicked at $DIR/exported_symbol_good_unwind.rs:LL:CC: diff --git a/src/tools/miri/tests/panic/oob_subslice.stderr b/src/tools/miri/tests/panic/oob_subslice.stderr index c116f8eb525..46f0f643a47 100644 --- a/src/tools/miri/tests/panic/oob_subslice.stderr +++ b/src/tools/miri/tests/panic/oob_subslice.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/oob_subslice.rs:LL:CC: range end index 5 out of range for slice of length 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr index 1d057ea5eb4..be822bd0285 100644 --- a/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr +++ b/src/tools/miri/tests/panic/overflowing-lsh-neg.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-lsh-neg.rs:LL:CC: attempt to shift left with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr index d1a79400bfa..fc090aba5fd 100644 --- a/src/tools/miri/tests/panic/overflowing-rsh-1.stderr +++ b/src/tools/miri/tests/panic/overflowing-rsh-1.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-rsh-1.rs:LL:CC: attempt to shift right with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr index 612b0c0c4c2..77160e1870f 100644 --- a/src/tools/miri/tests/panic/overflowing-rsh-2.stderr +++ b/src/tools/miri/tests/panic/overflowing-rsh-2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/overflowing-rsh-2.rs:LL:CC: attempt to shift right with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic2.stderr b/src/tools/miri/tests/panic/panic2.stderr index 792c71346fd..f7408310093 100644 --- a/src/tools/miri/tests/panic/panic2.stderr +++ b/src/tools/miri/tests/panic/panic2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic2.rs:LL:CC: 42-panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic3.stderr b/src/tools/miri/tests/panic/panic3.stderr index f8016bc3912..32ba400e025 100644 --- a/src/tools/miri/tests/panic/panic3.stderr +++ b/src/tools/miri/tests/panic/panic3.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic3.rs:LL:CC: panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/panic4.stderr b/src/tools/miri/tests/panic/panic4.stderr index 67410bf3b1a..a8a23ee3ce1 100644 --- a/src/tools/miri/tests/panic/panic4.stderr +++ b/src/tools/miri/tests/panic/panic4.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/panic4.rs:LL:CC: 42-panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs b/src/tools/miri/tests/panic/target_feature_wasm.rs index 5056f32de44..c67d2983f78 100644 --- a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs +++ b/src/tools/miri/tests/panic/target_feature_wasm.rs @@ -2,7 +2,9 @@ //@compile-flags: -C target-feature=-simd128 fn main() { - // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 + // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. + // But if the compiler actually uses the target feature, it will lead to an error when the module is loaded. + // We emulate this with an "unsupported" error. assert!(!cfg!(target_feature = "simd128")); simd128_fn(); } diff --git a/src/tools/miri/tests/panic/transmute_fat2.stderr b/src/tools/miri/tests/panic/transmute_fat2.stderr index 2ee01d46931..021ca1c4b32 100644 --- a/src/tools/miri/tests/panic/transmute_fat2.stderr +++ b/src/tools/miri/tests/panic/transmute_fat2.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/transmute_fat2.rs:LL:CC: index out of bounds: the len is 0 but the index is 0 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr index d0a7d8dafc5..fcc4220bfce 100644 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr +++ b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/unsupported_foreign_function.rs:LL:CC: unsupported Miri functionality: can't call foreign function `foo` on $OS note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/panic/unsupported_syscall.stderr b/src/tools/miri/tests/panic/unsupported_syscall.stderr index f802159cb1c..660cfba8900 100644 --- a/src/tools/miri/tests/panic/unsupported_syscall.stderr +++ b/src/tools/miri/tests/panic/unsupported_syscall.stderr @@ -1,4 +1,4 @@ thread 'main' panicked at $DIR/unsupported_syscall.rs:LL:CC: unsupported Miri functionality: can't execute syscall with ID 0 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs index e28cafd3c28..052ce73de23 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs @@ -1,8 +1,7 @@ //@only-target-linux -#![feature(exposed_provenance)] // Needed for fn test_pointer() +#![feature(strict_provenance)] use std::convert::TryInto; -use std::mem::MaybeUninit; fn main() { test_epoll_socketpair(); @@ -17,7 +16,6 @@ fn main() { test_no_notification_for_unregister_flag(); test_epoll_ctl_mod(); test_epoll_ctl_del(); - test_pointer(); test_two_same_fd_in_same_epoll_instance(); test_epoll_wait_maxevent_zero(); test_socketpair_epollerr(); @@ -261,24 +259,6 @@ fn test_epoll_eventfd() { check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]); } -fn test_pointer() { - // Create an epoll instance. - let epfd = unsafe { libc::epoll_create1(0) }; - assert_ne!(epfd, -1); - - // Create a socketpair instance. - let mut fds = [-1, -1]; - let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; - assert_eq!(res, 0); - - // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET - let data = MaybeUninit::<u64>::uninit().as_ptr(); - let mut ev = - libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: data.expose_provenance() as u64 }; - let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; - assert_eq!(res, 0); -} - // When read/write happened on one side of the socketpair, only the other side will be notified. fn test_epoll_socketpair_both_sides() { // Create an epoll instance. @@ -543,9 +523,9 @@ fn test_epoll_wait_maxevent_zero() { // Create an epoll instance. let epfd = unsafe { libc::epoll_create1(0) }; assert_ne!(epfd, -1); - // It is ok to use uninitialised pointer here because it will error out before the - // pointer actually get accessed. - let array_ptr = MaybeUninit::<libc::epoll_event>::uninit().as_mut_ptr(); + // It is ok to use a dangling pointer here because it will error out before the + // pointer actually gets accessed. + let array_ptr = std::ptr::without_provenance_mut::<libc::epoll_event>(0x100); let res = unsafe { libc::epoll_wait(epfd, array_ptr, 0, 0) }; let e = std::io::Error::last_os_error(); assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); diff --git a/src/tools/miri/tests/pass/panic/catch_panic.stderr b/src/tools/miri/tests/pass/panic/catch_panic.stderr index a472a5d80cb..f61b39493ed 100644 --- a/src/tools/miri/tests/pass/panic/catch_panic.stderr +++ b/src/tools/miri/tests/pass/panic/catch_panic.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: Hello from std::panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect Caught panic message (&str): Hello from std::panic thread 'main' panicked at $DIR/catch_panic.rs:LL:CC: Hello from std::panic: 1 diff --git a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr index b2a5cf4922c..fe0d16ca78a 100644 --- a/src/tools/miri/tests/pass/panic/concurrent-panic.stderr +++ b/src/tools/miri/tests/pass/panic/concurrent-panic.stderr @@ -3,7 +3,7 @@ Thread 1 reported it has started thread '<unnamed>' panicked at $DIR/concurrent-panic.rs:LL:CC: panic in thread 2 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect Thread 2 blocking on thread 1 Thread 2 reported it has started Unlocking mutex diff --git a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr index 3efb4be40f9..a346d31f645 100644 --- a/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr +++ b/src/tools/miri/tests/pass/panic/nested_panic_caught.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/nested_panic_caught.rs:LL:CC: once note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'main' panicked at $DIR/nested_panic_caught.rs:LL:CC: twice stack backtrace: diff --git a/src/tools/miri/tests/pass/panic/thread_panic.stderr b/src/tools/miri/tests/pass/panic/thread_panic.stderr index bdfe4f98ba3..0fde5922c19 100644 --- a/src/tools/miri/tests/pass/panic/thread_panic.stderr +++ b/src/tools/miri/tests/pass/panic/thread_panic.stderr @@ -1,6 +1,6 @@ thread '<unnamed>' panicked at $DIR/thread_panic.rs:LL:CC: Hello! note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: in Miri, you may have to set `-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread 'childthread' panicked at $DIR/thread_panic.rs:LL:CC: Hello, world! diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs new file mode 100644 index 00000000000..e65fdc3fbed --- /dev/null +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-sha.rs @@ -0,0 +1,270 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=+sha,+sse2,+ssse3,+sse4.1 + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +macro_rules! rounds4 { + ($abef:ident, $cdgh:ident, $rest:expr, $i:expr) => {{ + let k = K32X4[$i]; + let kv = _mm_set_epi32(k[0] as i32, k[1] as i32, k[2] as i32, k[3] as i32); + let t1 = _mm_add_epi32($rest, kv); + $cdgh = _mm_sha256rnds2_epu32($cdgh, $abef, t1); + let t2 = _mm_shuffle_epi32(t1, 0x0E); + $abef = _mm_sha256rnds2_epu32($abef, $cdgh, t2); + }}; +} + +macro_rules! schedule_rounds4 { + ( + $abef:ident, $cdgh:ident, + $w0:expr, $w1:expr, $w2:expr, $w3:expr, $w4:expr, + $i: expr + ) => {{ + $w4 = schedule($w0, $w1, $w2, $w3); + rounds4!($abef, $cdgh, $w4, $i); + }}; +} + +fn main() { + assert!(is_x86_feature_detected!("sha")); + assert!(is_x86_feature_detected!("sse2")); + assert!(is_x86_feature_detected!("ssse3")); + assert!(is_x86_feature_detected!("sse4.1")); + + unsafe { + test_sha256rnds2(); + test_sha256msg1(); + test_sha256msg2(); + test_sha256(); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256rnds2() { + let test_vectors = [ + ( + [0x3c6ef372, 0xa54ff53a, 0x1f83d9ab, 0x5be0cd19], + [0x6a09e667, 0xbb67ae85, 0x510e527f, 0x9b05688c], + [0x592340c6, 0x17386142, 0x91a0b7b1, 0x94ffa30c], + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + ), + ( + [0x6a09e667, 0xbb67ae85, 0x510e527f, 0x9b05688c], + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + [0x91a0b7b1, 0x94ffa30c, 0x592340c6, 0x17386142], + [0x7e7f3c9d, 0x78db9a20, 0xd82fe6ed, 0xaf1f2704], + ), + ( + [0xeef39c6c, 0x4e7dfbc1, 0x467a98f3, 0xeb3d5616], + [0x7e7f3c9d, 0x78db9a20, 0xd82fe6ed, 0xaf1f2704], + [0x1a89c3f6, 0xf3b6e817, 0x7a5a8511, 0x8bcc35cf], + [0xc9292f7e, 0x49137bd9, 0x7e5f9e08, 0xd10f9247], + ), + ]; + for (cdgh, abef, wk, expected) in test_vectors { + let output_reg = _mm_sha256rnds2_epu32(set_arr(cdgh), set_arr(abef), set_arr(wk)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256msg1() { + let test_vectors = [ + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ( + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0x2da4b536, 0x77f29328, 0x541a4d59, 0x6afb680c], + ), + ]; + for (v0, v1, expected) in test_vectors { + let output_reg = _mm_sha256msg1_epu32(set_arr(v0), set_arr(v1)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256msg2() { + let test_vectors = [ + ( + [0x801a28aa, 0xe75ff849, 0xb591b2cc, 0x8b64db2c], + [0x6f6d6521, 0x61776573, 0x20697320, 0x52757374], + [0xe7c46c4e, 0x8ce92ccc, 0xd3c0f3ce, 0xe9745c78], + ), + ( + [0x171911ae, 0xe75ff849, 0xb591b2cc, 0x8b64db2c], + [0xe7c46c4e, 0x8ce92ccc, 0xd3c0f3ce, 0xe9745c78], + [0xc17c6ea3, 0xc4d10083, 0x712910cd, 0x3f41c8ce], + ), + ( + [0x6ce67e04, 0x5fb6ff76, 0xe1037a25, 0x3ebc5bda], + [0xc17c6ea3, 0xc4d10083, 0x712910cd, 0x3f41c8ce], + [0xf5ab4eff, 0x83d732a5, 0x9bb941af, 0xdf1d0a8c], + ), + ]; + for (v4, v3, expected) in test_vectors { + let output_reg = _mm_sha256msg2_epu32(set_arr(v4), set_arr(v3)); + let mut output = [0u32; 4]; + _mm_storeu_si128(output.as_mut_ptr().cast(), output_reg); + // The values are stored as little endian, so we need to reverse them + output.reverse(); + assert_eq!(output, expected); + } +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn set_arr(x: [u32; 4]) -> __m128i { + _mm_set_epi32(x[0] as i32, x[1] as i32, x[2] as i32, x[3] as i32) +} + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn test_sha256() { + use std::fmt::Write; + + /// The initial state of the hash engine. + const INITIAL_STATE: [u32; 8] = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, + 0x5be0cd19, + ]; + + // We don't want to bother with hash finalization algorithm so we just feed constant data. + // This is the content that's being hashed - you can feed it to sha256sum and it'll output + // the same hash (beware of newlines though). + let first_block = *b"Rust is awesome!Rust is awesome!Rust is awesome!Rust is awesome!"; + // sha256 is fianlized by appending 0x80, then zeros and finally the data lenght at the + // end. + let mut final_block = [0; 64]; + final_block[0] = 0x80; + final_block[(64 - 8)..].copy_from_slice(&(8u64 * 64).to_be_bytes()); + + let mut state = INITIAL_STATE; + digest_blocks(&mut state, &[first_block, final_block]); + + // We compare strings because it's easier to check the hex and the output of panic. + let mut hash = String::new(); + for chunk in &state { + write!(hash, "{:08x}", chunk).expect("writing to String doesn't fail"); + } + assert_eq!(hash, "1b2293d21b17a0cb0c18737307c37333dea775eded18cefed45e50389f9f8184"); +} + +// Almost full SHA256 implementation copied from RustCrypto's sha2 crate +// https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/x86.rs + +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn schedule(v0: __m128i, v1: __m128i, v2: __m128i, v3: __m128i) -> __m128i { + let t1 = _mm_sha256msg1_epu32(v0, v1); + let t2 = _mm_alignr_epi8(v3, v2, 4); + let t3 = _mm_add_epi32(t1, t2); + _mm_sha256msg2_epu32(t3, v3) +} + +// we use unaligned loads with `__m128i` pointers +#[allow(clippy::cast_ptr_alignment)] +#[target_feature(enable = "sha,sse2,ssse3,sse4.1")] +unsafe fn digest_blocks(state: &mut [u32; 8], blocks: &[[u8; 64]]) { + #[allow(non_snake_case)] + let MASK: __m128i = + _mm_set_epi64x(0x0C0D_0E0F_0809_0A0Bu64 as i64, 0x0405_0607_0001_0203u64 as i64); + + let state_ptr: *const __m128i = state.as_ptr().cast(); + let dcba = _mm_loadu_si128(state_ptr.add(0)); + let efgh = _mm_loadu_si128(state_ptr.add(1)); + + let cdab = _mm_shuffle_epi32(dcba, 0xB1); + let efgh = _mm_shuffle_epi32(efgh, 0x1B); + let mut abef = _mm_alignr_epi8(cdab, efgh, 8); + let mut cdgh = _mm_blend_epi16(efgh, cdab, 0xF0); + + for block in blocks { + let abef_save = abef; + let cdgh_save = cdgh; + + let block_ptr: *const __m128i = block.as_ptr().cast(); + let mut w0 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(0)), MASK); + let mut w1 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(1)), MASK); + let mut w2 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(2)), MASK); + let mut w3 = _mm_shuffle_epi8(_mm_loadu_si128(block_ptr.add(3)), MASK); + let mut w4; + + rounds4!(abef, cdgh, w0, 0); + rounds4!(abef, cdgh, w1, 1); + rounds4!(abef, cdgh, w2, 2); + rounds4!(abef, cdgh, w3, 3); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 4); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 5); + schedule_rounds4!(abef, cdgh, w2, w3, w4, w0, w1, 6); + schedule_rounds4!(abef, cdgh, w3, w4, w0, w1, w2, 7); + schedule_rounds4!(abef, cdgh, w4, w0, w1, w2, w3, 8); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 9); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 10); + schedule_rounds4!(abef, cdgh, w2, w3, w4, w0, w1, 11); + schedule_rounds4!(abef, cdgh, w3, w4, w0, w1, w2, 12); + schedule_rounds4!(abef, cdgh, w4, w0, w1, w2, w3, 13); + schedule_rounds4!(abef, cdgh, w0, w1, w2, w3, w4, 14); + schedule_rounds4!(abef, cdgh, w1, w2, w3, w4, w0, 15); + + abef = _mm_add_epi32(abef, abef_save); + cdgh = _mm_add_epi32(cdgh, cdgh_save); + } + + let feba = _mm_shuffle_epi32(abef, 0x1B); + let dchg = _mm_shuffle_epi32(cdgh, 0xB1); + let dcba = _mm_blend_epi16(feba, dchg, 0xF0); + let hgef = _mm_alignr_epi8(dchg, feba, 8); + + let state_ptr_mut: *mut __m128i = state.as_mut_ptr().cast(); + _mm_storeu_si128(state_ptr_mut.add(0), dcba); + _mm_storeu_si128(state_ptr_mut.add(1), hgef); +} + +/// Swapped round constants for SHA-256 family of digests +pub static K32X4: [[u32; 4]; 16] = { + let mut res = [[0u32; 4]; 16]; + let mut i = 0; + while i < 16 { + res[i] = [K32[4 * i + 3], K32[4 * i + 2], K32[4 * i + 1], K32[4 * i]]; + i += 1; + } + res +}; + +/// Round constants for SHA-256 family of digests +pub static K32: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +]; diff --git a/src/tools/miri/tests/pass/weak_memory/weak.rs b/src/tools/miri/tests/pass/weak_memory/weak.rs index dac63eeeb0b..1b5c98cd518 100644 --- a/src/tools/miri/tests/pass/weak_memory/weak.rs +++ b/src/tools/miri/tests/pass/weak_memory/weak.rs @@ -18,11 +18,9 @@ struct EvilSend<T>(pub T); unsafe impl<T> Send for EvilSend<T> {} unsafe impl<T> Sync for EvilSend<T> {} -// We can't create static items because we need to run each test -// multiple times +// We can't create static items because we need to run each test multiple times. fn static_atomic(val: usize) -> &'static AtomicUsize { - let ret = Box::leak(Box::new(AtomicUsize::new(val))); - ret + Box::leak(Box::new(AtomicUsize::new(val))) } // Spins until it reads the given value @@ -33,7 +31,7 @@ fn reads_value(loc: &AtomicUsize, val: usize) -> usize { val } -fn relaxed() -> bool { +fn relaxed(initial_read: bool) -> bool { let x = static_atomic(0); let j1 = spawn(move || { x.store(1, Relaxed); @@ -47,7 +45,9 @@ fn relaxed() -> bool { j1.join().unwrap(); let r2 = j2.join().unwrap(); - r2 == 1 + // There are three possible values here: 0 (from the initial read), 1 (from the first relaxed + // read), and 2 (the last read). The last case is boring and we cover the other two. + r2 == if initial_read { 0 } else { 1 } } // https://www.doc.ic.ac.uk/~afd/homepages/papers/pdfs/2017/POPL.pdf Figure 8 @@ -74,7 +74,6 @@ fn seq_cst() -> bool { fn initialization_write(add_fence: bool) -> bool { let x = static_atomic(11); - assert_eq!(x.load(Relaxed), 11); // work around https://github.com/rust-lang/miri/issues/2164 let wait = static_atomic(0); @@ -112,11 +111,8 @@ fn faa_replaced_by_load() -> bool { } let x = static_atomic(0); - assert_eq!(x.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 let y = static_atomic(0); - assert_eq!(y.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 let z = static_atomic(0); - assert_eq!(z.load(Relaxed), 0); // work around https://github.com/rust-lang/miri/issues/2164 // Since each thread is so short, we need to make sure that they truely run at the same time // Otherwise t1 will finish before t2 even starts @@ -146,7 +142,8 @@ fn assert_once(f: fn() -> bool) { } pub fn main() { - assert_once(relaxed); + assert_once(|| relaxed(false)); + assert_once(|| relaxed(true)); assert_once(seq_cst); assert_once(|| initialization_write(false)); assert_once(|| initialization_write(true)); diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 1a13d56b0e4..77df6e7beb5 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -12,3 +12,4 @@ regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace gimli = "0.31.0" build_helper = { path = "../build_helper" } serde_json = "1.0" +libc = "0.2" diff --git a/src/tools/run-make-support/src/env.rs b/src/tools/run-make-support/src/env.rs index e6460fb93d3..9acbb16d73e 100644 --- a/src/tools/run-make-support/src/env.rs +++ b/src/tools/run-make-support/src/env.rs @@ -24,3 +24,11 @@ pub fn env_var_os(name: &str) -> OsString { pub fn no_debug_assertions() -> bool { std::env::var_os("NO_DEBUG_ASSERTIONS").is_some() } + +/// A wrapper around [`std::env::set_current_dir`] which includes the directory +/// path in the panic message. +#[track_caller] +pub fn set_current_dir<P: AsRef<std::path::Path>>(dir: P) { + std::env::set_current_dir(dir.as_ref()) + .expect(&format!("could not set current directory to \"{}\"", dir.as_ref().display())); +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index fc20fd3b2e8..989d00d4c2f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -36,6 +36,7 @@ pub mod rfs { // Re-exports of third-party library crates. pub use bstr; pub use gimli; +pub use libc; pub use object; pub use regex; pub use serde_json; @@ -64,7 +65,7 @@ pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc}; pub use diff::{diff, Diff}; /// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers. -pub use env::{env_var, env_var_os}; +pub use env::{env_var, env_var_os, set_current_dir}; /// Convenience helpers for running binaries and other commands. pub use run::{cmd, run, run_fail, run_with_args}; diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs index 1e6e44c4584..87901793a92 100644 --- a/src/tools/run-make-support/src/path_helpers.rs +++ b/src/tools/run-make-support/src/path_helpers.rs @@ -21,6 +21,7 @@ pub fn cwd() -> PathBuf { /// # Example /// /// ```rust +/// # use run_make_support::path; /// let p = path("support_file.txt"); /// ``` pub fn path<P: AsRef<Path>>(p: P) -> PathBuf { diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs index 12088e5d3b5..3eeba6fd526 100644 --- a/src/tools/run-make-support/src/run.rs +++ b/src/tools/run-make-support/src/run.rs @@ -29,6 +29,7 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command { } env::join_paths(paths.iter()).unwrap() }); + cmd.env("LC_ALL", "C"); // force english locale if is_windows() { let mut paths = vec![]; @@ -84,5 +85,6 @@ pub fn run_fail(name: &str) -> CompletedProcess { pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command { let mut command = Command::new(program); set_host_rpath(&mut command); + command.env("LC_ALL", "C"); // force english locale command } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index f55abb513b8..22d1e93bf39 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -6,9 +6,7 @@ run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile -run-make/libtest-thread-limit/Makefile run-make/macos-deployment-target/Makefile run-make/split-debuginfo/Makefile run-make/symbol-mangling-hashed/Makefile run-make/translation/Makefile -run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs index 6a58d58dbde..08f6a3909f8 100644 --- a/src/tools/tidy/src/edition.rs +++ b/src/tools/tidy/src/edition.rs @@ -1,4 +1,4 @@ -//! Tidy check to ensure that crate `edition` is '2018' or '2021'. +//! Tidy check to ensure that crate `edition` is '2021' or '2024'. use std::path::Path; @@ -12,7 +12,9 @@ pub fn check(path: &Path, bad: &mut bool) { return; } - let is_2021 = contents.lines().any(|line| line.trim() == "edition = \"2021\""); + let is_current_edition = contents + .lines() + .any(|line| line.trim() == "edition = \"2021\"" || line.trim() == "edition = \"2024\""); let is_workspace = contents.lines().any(|line| line.trim() == "[workspace]"); let is_package = contents.lines().any(|line| line.trim() == "[package]"); @@ -20,10 +22,10 @@ pub fn check(path: &Path, bad: &mut bool) { // Check that all packages use the 2021 edition. Virtual workspaces don't allow setting an // edition, so these shouldn't be checked. - if is_package && !is_2021 { + if is_package && !is_current_edition { tidy_error!( bad, - "{} doesn't have `edition = \"2021\"` on a separate line", + "{} doesn't have `edition = \"2021\"` or `edition = \"2024\"` on a separate line", file.display() ); } diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 3e2a4773703..f36345670e3 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -5,10 +5,12 @@ //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec] needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! +#![feature(auto_traits)] #[rustc_builtin_macro] macro_rules! asm { @@ -39,6 +41,8 @@ pub struct i32x2(i32, i32); #[repr(simd)] pub struct i64x1(i64); #[repr(simd)] +pub struct f16x4(f16, f16, f16, f16); +#[repr(simd)] pub struct f32x2(f32, f32); #[repr(simd)] pub struct f64x1(f64); @@ -51,30 +55,42 @@ pub struct i32x4(i32, i32, i32, i32); #[repr(simd)] pub struct i64x2(i64, i64); #[repr(simd)] +pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +#[repr(simd)] pub struct f32x4(f32, f32, f32, f32); #[repr(simd)] pub struct f64x2(f64, f64); impl Copy for i8 {} impl Copy for i16 {} +impl Copy for f16 {} impl Copy for i32 {} impl Copy for f32 {} impl Copy for i64 {} impl Copy for f64 {} +impl Copy for f128 {} impl Copy for ptr {} impl Copy for i8x8 {} impl Copy for i16x4 {} impl Copy for i32x2 {} impl Copy for i64x1 {} +impl Copy for f16x4 {} impl Copy for f32x2 {} impl Copy for f64x1 {} impl Copy for i8x16 {} impl Copy for i16x8 {} impl Copy for i32x4 {} impl Copy for i64x2 {} +impl Copy for f16x8 {} impl Copy for f32x4 {} impl Copy for f64x2 {} +// FIXME(f16_f128): Only needed for FIXME in check! and check_reg! +#[lang = "freeze"] +unsafe auto trait Freeze {} +#[lang = "unpin"] +auto trait Unpin {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -111,38 +127,44 @@ pub unsafe fn issue_75761() { macro_rules! check { ($func:ident $ty:ident $class:ident $mov:literal $modifier:literal) => { + // FIXME(f16_f128): Change back to `$func(x: $ty) -> $ty` once arm64ec can pass and return + // `f16` and `f128` without LLVM erroring. + // LLVM issue: <https://github.com/llvm/llvm-project/issues/94434> #[no_mangle] - pub unsafe fn $func(x: $ty) -> $ty { + pub unsafe fn $func(inp: &$ty, out: &mut $ty) { // Hack to avoid function merging extern "Rust" { fn dont_merge(s: &str); } dont_merge(stringify!($func)); + let x = *inp; let y; asm!( concat!($mov, " {:", $modifier, "}, {:", $modifier, "}"), out($class) y, in($class) x ); - y + *out = y; } }; } macro_rules! check_reg { ($func:ident $ty:ident $reg:tt $mov:literal) => { + // FIXME(f16_f128): See FIXME in `check!` #[no_mangle] - pub unsafe fn $func(x: $ty) -> $ty { + pub unsafe fn $func(inp: &$ty, out: &mut $ty) { // Hack to avoid function merging extern "Rust" { fn dont_merge(s: &str); } dont_merge(stringify!($func)); + let x = *inp; let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); - y + *out = y; } }; } @@ -159,6 +181,12 @@ check!(reg_i8 i8 reg "mov" ""); // CHECK: //NO_APP check!(reg_i16 i16 reg "mov" ""); +// CHECK-LABEL: {{("#)?}}reg_f16{{"?}} +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check!(reg_f16 f16 reg "mov" ""); + // CHECK-LABEL: {{("#)?}}reg_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -201,6 +229,12 @@ check!(vreg_i8 i8 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i16 i16 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16 f16 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_i32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -225,6 +259,12 @@ check!(vreg_i64 i64 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_f64 f64 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f128 f128 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -255,6 +295,12 @@ check!(vreg_i32x2 i32x2 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i64x1 i64x1 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16x4 f16x4 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -291,6 +337,12 @@ check!(vreg_i32x4 i32x4 vreg "fmov" "s"); // CHECK: //NO_APP check!(vreg_i64x2 i64x2 vreg "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_f16x8 f16x8 vreg "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -315,6 +367,12 @@ check!(vreg_low16_i8 i8 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i16 i16 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16 f16 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -333,6 +391,12 @@ check!(vreg_low16_i64 i64 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_f64 f64 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f128 f128 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -363,6 +427,12 @@ check!(vreg_low16_i32x2 i32x2 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i64x1 i64x1 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16x4 f16x4 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -399,6 +469,12 @@ check!(vreg_low16_i32x4 i32x4 vreg_low16 "fmov" "s"); // CHECK: //NO_APP check!(vreg_low16_i64x2 i64x2 vreg_low16 "fmov" "s"); +// CHECK-LABEL: {{("#)?}}vreg_low16_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} +// CHECK: //NO_APP +check!(vreg_low16_f16x8 f16x8 vreg_low16 "fmov" "s"); + // CHECK-LABEL: {{("#)?}}vreg_low16_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} @@ -423,6 +499,12 @@ check_reg!(x0_i8 i8 "x0" "mov"); // CHECK: //NO_APP check_reg!(x0_i16 i16 "x0" "mov"); +// CHECK-LABEL: {{("#)?}}x0_f16{{"?}} +// CHECK: //APP +// CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} +// CHECK: //NO_APP +check_reg!(x0_f16 f16 "x0" "mov"); + // CHECK-LABEL: {{("#)?}}x0_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} @@ -465,6 +547,12 @@ check_reg!(v0_i8 i8 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i16 i16 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16 f16 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_i32{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -489,6 +577,12 @@ check_reg!(v0_i64 i64 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_f64 f64 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f128{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f128 f128 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_ptr{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -519,6 +613,12 @@ check_reg!(v0_i32x2 i32x2 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i64x1 i64x1 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16x4{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16x4 f16x4 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 @@ -555,6 +655,12 @@ check_reg!(v0_i32x4 i32x4 "s0" "fmov"); // CHECK: //NO_APP check_reg!(v0_i64x2 i64x2 "s0" "fmov"); +// CHECK-LABEL: {{("#)?}}v0_f16x8{{"?}} +// CHECK: //APP +// CHECK: fmov s0, s0 +// CHECK: //NO_APP +check_reg!(v0_f16x8 f16x8 "s0" "fmov"); + // CHECK-LABEL: {{("#)?}}v0_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 diff --git a/tests/assembly/struct-target-features.rs b/tests/assembly/struct-target-features.rs new file mode 100644 index 00000000000..cc86fbaa840 --- /dev/null +++ b/tests/assembly/struct-target-features.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -O +//@ assembly-output: emit-asm +//@ only-x86_64 + +#![crate_type = "lib"] +#![feature(struct_target_features)] + +// Check that a struct_target_features type causes the compiler to effectively inline intrinsics. + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "fma")] +struct Fma {} + +pub fn add_simple(_: Avx, v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) { + // CHECK-NOT: call + // CHECK-DAG: vaddps + let r1 = unsafe { _mm256_add_ps(v, v) }; + // CHECK-DAG: vfmadd213ps + let r2 = unsafe { _mm256_fmadd_ps(v, v, v) }; + (r1, r2) +} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index c3a083321e2..6f0a200a08c 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -66,6 +66,9 @@ //@ revisions: aarch64_unknown_teeos //@ [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos //@ [aarch64_unknown_teeos] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_trusty +//@ [aarch64_unknown_trusty] compile-flags: --target aarch64-unknown-trusty +//@ [aarch64_unknown_trusty] needs-llvm-components: aarch64 //@ revisions: aarch64_wrs_vxworks //@ [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks //@ [aarch64_wrs_vxworks] needs-llvm-components: aarch64 @@ -153,6 +156,9 @@ //@ revisions: armv7_unknown_netbsd_eabihf //@ [armv7_unknown_netbsd_eabihf] compile-flags: --target armv7-unknown-netbsd-eabihf //@ [armv7_unknown_netbsd_eabihf] needs-llvm-components: arm +//@ revisions: armv7_unknown_trusty +//@ [armv7_unknown_trusty] compile-flags: --target armv7-unknown-trusty +//@ [armv7_unknown_trusty] needs-llvm-components: arm //@ revisions: armv7_wrs_vxworks_eabihf //@ [armv7_wrs_vxworks_eabihf] compile-flags: --target armv7-wrs-vxworks-eabihf //@ [armv7_wrs_vxworks_eabihf] needs-llvm-components: arm diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs index 31efdda1bfa..67b7ff99ae2 100644 --- a/tests/assembly/x86_64-cmp.rs +++ b/tests/assembly/x86_64-cmp.rs @@ -1,6 +1,9 @@ -//@ revisions: DEBUG OPTIM +//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM //@ [DEBUG] compile-flags: -C opt-level=0 -//@ [OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-PRE-20-OPTIM] ignore-llvm-version: 20 - 99 +//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3 +//@ [LLVM-20-OPTIM] min-llvm-version: 20 //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel //@ only-x86_64 @@ -21,12 +24,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovge - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovge + // LLVM-PRE-20-OPTIM: ret + // + // LLVM-20-OPTIM: cmp + // LLVM-20-OPTIM: setl + // LLVM-20-OPTIM: setg + // LLVM-20-OPTIM: sub + // LLVM-20-OPTIM: ret three_way_compare(a, b) } @@ -41,11 +50,16 @@ pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovae - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovae + // LLVM-PRE-20-OPTIM: ret + // + // LLVM-20-OPTIM: cmp + // LLVM-20-OPTIM: seta + // LLVM-20-OPTIM: sbb + // LLVM-20-OPTIM: ret three_way_compare(a, b) } diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index bba112b246f..8df68d8d490 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -1,6 +1,9 @@ // This is test for more optimal Ord implementation for integers. // See <https://github.com/rust-lang/rust/issues/63758> for more info. +//@ revisions: llvm-pre-20 llvm-20 +//@ [llvm-20] min-llvm-version: 20 +//@ [llvm-pre-20] ignore-llvm-version: 20 - 99 //@ compile-flags: -C opt-level=3 #![crate_type = "lib"] @@ -10,19 +13,21 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { - // CHECK: icmp slt - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.scmp.i8.i64 + // llvm-pre-20: icmp slt + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { - // CHECK: icmp ult - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.ucmp.i8.i32 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs new file mode 100644 index 00000000000..d5faac44836 --- /dev/null +++ b/tests/codegen/naked-fn/aligned.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ needs-asm-support +//@ ignore-arm no "ret" mnemonic + +#![crate_type = "lib"] +#![feature(naked_functions, fn_align)] +use std::arch::asm; + +// CHECK: Function Attrs: naked +// CHECK-NEXT: define{{.*}}void @naked_empty() +// CHECK: align 16 +#[repr(align(16))] +#[no_mangle] +#[naked] +pub unsafe extern "C" fn naked_empty() { + // CHECK-NEXT: start: + // CHECK-NEXT: call void asm + // CHECK-NEXT: unreachable + asm!("ret", options(noreturn)); +} diff --git a/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs new file mode 100644 index 00000000000..a54a6d84a80 --- /dev/null +++ b/tests/codegen/sanitizer/cfi/add-cfi-normalize-integers-flag.rs @@ -0,0 +1,10 @@ +// Verifies that "cfi-normalize-integers" module flag is added. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers + +#![crate_type = "lib"] + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1} diff --git a/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs new file mode 100644 index 00000000000..d48e4016a16 --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-cfi-normalize-integers-flag.rs @@ -0,0 +1,21 @@ +// Verifies that "cfi-normalize-integers" module flag is added. +// +//@ revisions: aarch64 x86_64 +//@ [aarch64] compile-flags: --target aarch64-unknown-none +//@ [aarch64] needs-llvm-components: aarch64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"cfi-normalize-integers", i32 1} diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs new file mode 100644 index 00000000000..b4924719f4c --- /dev/null +++ b/tests/codegen/sanitizer/kcfi/add-kcfi-offset-flag.rs @@ -0,0 +1,21 @@ +// Verifies that "kcfi-offset" module flag is added. +// +//@ revisions: aarch64 x86_64 +//@ [aarch64] compile-flags: --target aarch64-unknown-none +//@ [aarch64] needs-llvm-components: aarch64 +//@ [x86_64] compile-flags: --target x86_64-unknown-none +//@ [x86_64] needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Z patchable-function-entry=4,3 + +#![feature(no_core, lang_items, patchable_function_entry)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn foo() {} + +// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-offset", i32 3} diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b4596ae2cb..1b2b63c3d1a 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -3,21 +3,21 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+v8a" feature is matched as optional as it isn't added when we -// are targeting older LLVM versions. Once the min supported version -// is LLVM-14 we can remove the optional regex matching for this feature. +// The "+fpmr" feature is matched as optional as it is only an explicit +// feature in LLVM 18. Once the min supported version is LLVM-19 the optional +// regex matching for this feature can be removed. //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/crashes/123693.rs b/tests/crashes/123693.rs index c2e192092be..c3236322c6e 100644 --- a/tests/crashes/123693.rs +++ b/tests/crashes/123693.rs @@ -3,11 +3,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::NOTHING }>, + Dst: TransmuteFrom<Src, { Assume::NOTHING }>, { } } diff --git a/tests/crashes/124207.rs b/tests/crashes/124207.rs index a4e1c551890..a11eedb140a 100644 --- a/tests/crashes/124207.rs +++ b/tests/crashes/124207.rs @@ -4,6 +4,6 @@ trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; trait AnotherTrait {} -impl<T: std::mem::BikeshedIntrinsicFrom<(), ()>> AnotherTrait for T {} +impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {} impl AnotherTrait for OpaqueType {} pub fn main() {} diff --git a/tests/crashes/125881.rs b/tests/crashes/125881.rs index 98331d3c974..a38f1891b61 100644 --- a/tests/crashes/125881.rs +++ b/tests/crashes/125881.rs @@ -3,6 +3,6 @@ #![feature(transmutability)] #![feature(unboxed_closures,effects)] -const fn test() -> impl std::mem::BikeshedIntrinsicFrom() { +const fn test() -> impl std::mem::TransmuteFrom() { || {} } diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs index c0604b90a67..728578179ed 100644 --- a/tests/crashes/126267.rs +++ b/tests/crashes/126267.rs @@ -14,11 +14,11 @@ pub enum Error { } mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, // safety is NOT assumed + Dst: TransmuteFrom<Src>, // safety is NOT assumed { } } diff --git a/tests/crashes/126377.rs b/tests/crashes/126377.rs index f8b9b693b65..f6727bcc0a4 100644 --- a/tests/crashes/126377.rs +++ b/tests/crashes/126377.rs @@ -4,7 +4,7 @@ #![feature(generic_const_exprs)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -15,7 +15,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { } >, diff --git a/tests/crashes/126966.rs b/tests/crashes/126966.rs index edeedc68c40..2c9f1a70f4f 100644 --- a/tests/crashes/126966.rs +++ b/tests/crashes/126966.rs @@ -1,10 +1,10 @@ //@ known-bug: rust-lang/rust#126966 mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } diff --git a/tests/crashes/127972.rs b/tests/crashes/127972.rs index d0764f875db..797dd7e6020 100644 --- a/tests/crashes/127972.rs +++ b/tests/crashes/127972.rs @@ -1,5 +1,5 @@ //@ known-bug: #127962 -#![feature(generic_const_exprs)] +#![feature(generic_const_exprs, const_arg_path)] fn zero_init<const usize: usize>() -> Substs1<{ (N) }> { Substs1([0; { (usize) }]) diff --git a/tests/crashes/128016.rs b/tests/crashes/128016.rs deleted file mode 100644 index d23721ae14e..00000000000 --- a/tests/crashes/128016.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #128016 -macro_rules! len { - () => { - target - }; -} - -fn main() { - let val: [str; len!()] = []; -} diff --git a/tests/crashes/129205.rs b/tests/crashes/129205.rs deleted file mode 100644 index f328fca247a..00000000000 --- a/tests/crashes/129205.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: rust-lang/rust#129205 - -fn x<T: Copy>() { - T::try_from(); -} diff --git a/tests/crashes/129216.rs b/tests/crashes/129216.rs deleted file mode 100644 index 0ad6bc5c71b..00000000000 --- a/tests/crashes/129216.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#129216 -//@ only-linux - -trait Mirror { - type Assoc; -} - -struct Foo; - -fn main() { - <Foo as Mirror>::Assoc::new(); -} diff --git a/tests/incremental/decl_macro.rs b/tests/incremental/decl_macro.rs new file mode 100644 index 00000000000..74810ae4227 --- /dev/null +++ b/tests/incremental/decl_macro.rs @@ -0,0 +1,34 @@ +//@ revisions: rpass1 rpass2 + +// issue#112680 + +#![feature(decl_macro)] + +pub trait T { + type Key; + fn index_from_key(key: Self::Key) -> usize; +} + +pub macro m($key_ty:ident, $val_ty:ident) { + struct $key_ty { + inner: usize, + } + + impl T for $val_ty { + type Key = $key_ty; + + fn index_from_key(key: Self::Key) -> usize { + key.inner + } + } +} + +m!(TestId, Test); + +#[cfg(rpass1)] +struct Test(u32); + +#[cfg(rpass2)] +struct Test; + +fn main() {} diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir index e8ad5cd8d16..293aa37944d 100644 --- a/tests/mir-opt/issue_72181_1.main.built.after.mir +++ b/tests/mir-opt/issue_72181_1.main.built.after.mir @@ -19,7 +19,7 @@ fn main() -> () { StorageLive(_2); StorageLive(_3); _3 = (); - _2 = transmute::<(), Void>(move _3) -> bb4; + _2 = std::intrinsics::transmute::<(), Void>(move _3) -> bb4; } bb1: { diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff index 71e84fdd881..b1104c70e46 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-abort.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as i8 (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff index 71e84fdd881..b1104c70e46 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as i8 (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff index 37232b826c1..169e48a31dd 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-abort.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as *const T (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff index 37232b826c1..169e48a31dd 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; +- _0 = std::intrinsics::transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; + _0 = move _2 as *const T (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff index 8ac70f99ad2..7098b4d3168 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as std::boxed::Box<Never> (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff index 8ac70f99ad2..7098b4d3168 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as std::boxed::Box<Never> (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff index c2c4ec0003c..06225fffd7c 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &mut Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff index c2c4ec0003c..06225fffd7c 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &mut Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff index 1b516a1f53b..dd6ab3a9c97 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-abort.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff index 1b516a1f53b..dd6ab3a9c97 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -10,7 +10,7 @@ bb0: { StorageLive(_1); -- _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; +- _1 = std::intrinsics::transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; + _1 = const 1_usize as &Never (Transmute); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff index eab969e9fe5..6571f3d9db8 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-abort.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<(), Never>(move _2) -> unwind unreachable; +- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable; + _0 = move _2 as Never (Transmute); + unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff index eab969e9fe5..6571f3d9db8 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); _2 = copy _1; -- _0 = transmute::<(), Never>(move _2) -> unwind unreachable; +- _0 = std::intrinsics::transmute::<(), Never>(move _2) -> unwind unreachable; + _0 = move _2 as Never (Transmute); + unreachable; } diff --git a/tests/run-make/rust-lld-compress-debug-sections/main.rs b/tests/run-make/compressed-debuginfo-zstd/main.rs index f328e4d9d04..f328e4d9d04 100644 --- a/tests/run-make/rust-lld-compress-debug-sections/main.rs +++ b/tests/run-make/compressed-debuginfo-zstd/main.rs diff --git a/tests/run-make/compressed-debuginfo-zstd/rmake.rs b/tests/run-make/compressed-debuginfo-zstd/rmake.rs new file mode 100644 index 00000000000..8356373e949 --- /dev/null +++ b/tests/run-make/compressed-debuginfo-zstd/rmake.rs @@ -0,0 +1,42 @@ +// Checks debuginfo compression both for the always-enabled zlib, and when the optional zstd is +// enabled: +// - via rustc's `debuginfo-compression`, +// - and via rust-lld's `compress-debug-sections` + +//@ needs-llvm-zstd: we want LLVM/LLD to be built with zstd support +//@ needs-rust-lld: the system linker will most likely not support zstd +//@ only-linux +//@ ignore-cross-compile + +use run_make_support::{llvm_readobj, run_in_tmpdir, Rustc}; + +fn check_compression(compression: &str, to_find: &str) { + // check compressed debug sections via rustc flag + prepare_and_check(to_find, |rustc| { + rustc.arg(&format!("-Zdebuginfo-compression={compression}")) + }); + + // check compressed debug sections via rust-lld flag + prepare_and_check(to_find, |rustc| { + rustc.link_arg(&format!("-Wl,--compress-debug-sections={compression}")) + }); +} + +fn prepare_and_check<F: FnOnce(&mut Rustc) -> &mut Rustc>(to_find: &str, prepare_rustc: F) { + run_in_tmpdir(|| { + let mut rustc = Rustc::new(); + rustc + .arg("-Zlinker-features=+lld") + .arg("-Clink-self-contained=+linker") + .arg("-Zunstable-options") + .arg("-Cdebuginfo=full") + .input("main.rs"); + prepare_rustc(&mut rustc).run(); + llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find); + }); +} + +fn main() { + check_compression("zlib", "ZLIB"); + check_compression("zstd", "ZSTD"); +} diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 13585edf6cc..95a9011669e 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -27,7 +27,7 @@ fn main() { | | | required by a bound introduced by this call | -help: there are multiple different versions of crate `dependency` the your dependency graph +help: there are multiple different versions of crate `dependency` in the dependency graph --> multiple-dep-versions.rs:1:1 | 1 | extern crate dep_2_reexport; diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py deleted file mode 100644 index 1bb8bf6d7fd..00000000000 --- a/tests/run-make/debugger-visualizer-dep-info/foo.py +++ /dev/null @@ -1 +0,0 @@ -# empty diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs index 3aede2215ea..3539b305be3 100644 --- a/tests/run-make/debugger-visualizer-dep-info/main.rs +++ b/tests/run-make/debugger-visualizer-dep-info/main.rs @@ -1,4 +1,4 @@ -#![debugger_visualizer(gdb_script_file = "foo.py")] +#![debugger_visualizer(gdb_script_file = "my_gdb_script.py")] fn main() { const _UNUSED: u32 = { diff --git a/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py new file mode 100644 index 00000000000..d319792657e --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/my_gdb_script.py @@ -0,0 +1,6 @@ +# This is a Python script, but we don't actually run it. +# So if you're trying to remove Python scripts from the test suite, +# be aware that there's no value in trying to get rid of this one. +# +# It just needs to exist so that the compiler can embed it via +# `#![debugger_visualizer(gdb_script_file = "...")]`. diff --git a/tests/run-make/debugger-visualizer-dep-info/rmake.rs b/tests/run-make/debugger-visualizer-dep-info/rmake.rs index 65ffb2373e7..f5cf39157ac 100644 --- a/tests/run-make/debugger-visualizer-dep-info/rmake.rs +++ b/tests/run-make/debugger-visualizer-dep-info/rmake.rs @@ -6,6 +6,6 @@ use run_make_support::{invalid_utf8_contains, rustc}; fn main() { rustc().emit("dep-info").input("main.rs").run(); - invalid_utf8_contains("main.d", "foo.py"); + invalid_utf8_contains("main.d", "my_gdb_script.py"); invalid_utf8_contains("main.d", "my_visualizers/bar.natvis"); } diff --git a/tests/run-make/embed-source-dwarf/main.rs b/tests/run-make/embed-source-dwarf/main.rs new file mode 100644 index 00000000000..c80af84f414 --- /dev/null +++ b/tests/run-make/embed-source-dwarf/main.rs @@ -0,0 +1,2 @@ +// hello +fn main() {} diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs new file mode 100644 index 00000000000..06d550121b0 --- /dev/null +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -0,0 +1,70 @@ +//@ ignore-windows +//@ ignore-apple + +// LLVM 17's embed-source implementation requires that source code is attached +// for all files in the output DWARF debug info. This restriction was lifted in +// LLVM 18 (87e22bdd2bd6d77d782f9d64b3e3ae5bdcd5080d). +//@ min-llvm-version: 18 + +// This test should be replaced with one in tests/debuginfo once we can easily +// tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB +// like setting an invalid source map path don't appear to work, maybe this'll +// become easier once GDB supports DWARFv6? + +use std::collections::HashMap; +use std::path::PathBuf; +use std::rc::Rc; + +use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian}; +use object::{Object, ObjectSection}; +use run_make_support::{gimli, object, rfs, rustc}; + +fn main() { + let output = PathBuf::from("embed-source-main"); + rustc() + .input("main.rs") + .output(&output) + .arg("-g") + .arg("-Zembed-source=yes") + .arg("-Zdwarf-version=5") + .run(); + let output = rfs::read(output); + let obj = object::File::parse(output.as_slice()).unwrap(); + let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big }; + let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> { + let data = obj.section_by_name(section.name()).map(|s| s.uncompressed_data().unwrap()); + Ok(EndianRcSlice::new(Rc::from(data.unwrap_or_default().as_ref()), endian)) + }) + .unwrap(); + + let mut sources = HashMap::new(); + + let mut iter = dwarf.units(); + while let Some(header) = iter.next().unwrap() { + let unit = dwarf.unit(header).unwrap(); + let unit = unit.unit_ref(&dwarf); + + if let Some(program) = &unit.line_program { + let header = program.header(); + for file in header.file_names() { + if let Some(source) = file.source() { + let path = unit + .attr_string(file.path_name()) + .unwrap() + .to_string_lossy() + .unwrap() + .to_string(); + let source = + unit.attr_string(source).unwrap().to_string_lossy().unwrap().to_string(); + if !source.is_empty() { + sources.insert(path, source); + } + } + } + } + } + + dbg!(&sources); + assert_eq!(sources.len(), 1); + assert_eq!(sources.get("main.rs").unwrap(), "// hello\nfn main() {}\n"); +} diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index e5482af10bb..483f298776c 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -20,6 +20,7 @@ fn main() { .input("x.rs") .run(); assert!(Path::new("invocation-only/search-index-xxx.js").exists()); + assert!(Path::new("invocation-only/crates-xxx.js").exists()); assert!(Path::new("invocation-only/settings.html").exists()); assert!(Path::new("invocation-only/x/all.html").exists()); assert!(Path::new("invocation-only/x/index.html").exists()); diff --git a/tests/run-make/libtest-junit/validate_junit.py b/tests/run-make/libtest-junit/validate_junit.py index 0d9b34a3cf7..f92473751b0 100755 --- a/tests/run-make/libtest-junit/validate_junit.py +++ b/tests/run-make/libtest-junit/validate_junit.py @@ -1,5 +1,15 @@ #!/usr/bin/env python +# Trivial Python script that reads lines from stdin, and checks that each line +# is a well-formed XML document. +# +# This takes advantage of the fact that Python has a built-in XML parser, +# whereas doing the same check in Rust would require us to pull in an XML +# crate just for this relatively-minor test. +# +# If you're trying to remove Python scripts from the test suite, think twice +# before removing this one. You could do so, but it's probably not worth it. + import sys import xml.etree.ElementTree as ET diff --git a/tests/run-make/libtest-thread-limit/Makefile b/tests/run-make/libtest-thread-limit/Makefile deleted file mode 100644 index 9496fa30159..00000000000 --- a/tests/run-make/libtest-thread-limit/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -# only-linux - -all: - $(RUSTC) test.rs --test --target $(TARGET) - $(shell ulimit -p 0 && $(call RUN,test)) diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs new file mode 100644 index 00000000000..be0eeaf1717 --- /dev/null +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -0,0 +1,64 @@ +// libtest used to panic if it hit the thread limit. This often resulted in spurious test failures +// (thread 'main' panicked at 'called Result::unwrap() on an Err value: Os +// { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }' ... +// error: test failed, to rerun pass '--lib'). +// Since the fix in #81546, the test should continue to run synchronously +// if it runs out of threads. Therefore, this test's final execution step +// should succeed without an error. +// See https://github.com/rust-lang/rust/pull/81546 + +//@ only-linux +// Reason: thread limit modification +//@ ignore-cross-compile +// Reason: this test fails armhf-gnu, reasons unknown + +use std::ffi::{self, CStr, CString}; +use std::path::PathBuf; + +use run_make_support::{libc, run, rustc}; + +fn main() { + rustc().input("test.rs").arg("--test").run(); + + // We need to emulate an environment for libtest where threads are exhausted and spawning + // new threads are guaranteed to fail. This was previously achieved by ulimit shell builtin + // that called out to prlimit64 underneath to set resource limits (specifically thread + // number limits). Now that we don't have a shell, we need to implement that ourselves. + // See https://linux.die.net/man/2/setrlimit + + // The fork + exec is required because we cannot first try to limit the number of + // processes/threads to 1 and then try to spawn a new process to run the test. We need to + // setrlimit and run the libtest test program in the same process. + let pid = unsafe { libc::fork() }; + assert!(pid >= 0); + + // If the process ID is 0, this is the child process responsible for running the test + // program. + if pid == 0 { + let test = CString::new("test").unwrap(); + // The argv array should be terminated with a NULL pointer. + let argv = [test.as_ptr(), std::ptr::null()]; + // rlim_cur is soft limit, rlim_max is hard limit. + // By setting the limit very low (max 1), we ensure that libtest is unable to create new + // threads. + let rlimit = libc::rlimit { rlim_cur: 1, rlim_max: 1 }; + // RLIMIT_NPROC: The maximum number of processes (or, more precisely on Linux, + // threads) that can be created for the real user ID of the calling process. Upon + // encountering this limit, fork(2) fails with the error EAGAIN. + // Therefore, set the resource limit to RLIMIT_NPROC. + let ret = unsafe { libc::setrlimit(libc::RLIMIT_NPROC, &rlimit as *const libc::rlimit) }; + assert_eq!(ret, 0); + + // Finally, execute the 2 tests in test.rs. + let ret = unsafe { libc::execv(test.as_ptr(), argv.as_ptr()) }; + assert_eq!(ret, 0); + } else { + // Otherwise, other process IDs indicate that this is the parent process. + + let mut status: libc::c_int = 0; + let ret = unsafe { libc::waitpid(pid, &mut status as *mut libc::c_int, 0) }; + assert_eq!(ret, pid); + assert!(libc::WIFEXITED(status)); + assert_eq!(libc::WEXITSTATUS(status), 0); + } +} diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs index 87e1d519171..d4eb1242615 100644 --- a/tests/run-make/libtest-thread-limit/test.rs +++ b/tests/run-make/libtest-thread-limit/test.rs @@ -10,7 +10,12 @@ fn spawn_thread_would_block() { THREAD_ID.set(thread::current().id()).unwrap(); } +// Tests are run in alphabetical order, and the second test is dependent on the +// first to set THREAD_ID. Do not rename the tests in such a way that `test_run_in_same_thread` +// would run before `spawn_thread_would_block`. +// See https://doc.rust-lang.org/rustc/tests/index.html#--shuffle + #[test] -fn run_in_same_thread() { +fn test_run_in_same_thread() { assert_eq!(*THREAD_ID.get().unwrap(), thread::current().id()); } diff --git a/tests/run-make/msvc-wholearchive/c.c b/tests/run-make/msvc-wholearchive/c.c new file mode 100644 index 00000000000..d6847845c68 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/c.c @@ -0,0 +1 @@ +// This page is intentionally left blank diff --git a/tests/run-make/msvc-wholearchive/dll.def b/tests/run-make/msvc-wholearchive/dll.def new file mode 100644 index 00000000000..d55819e0d5e --- /dev/null +++ b/tests/run-make/msvc-wholearchive/dll.def @@ -0,0 +1,4 @@ +LIBRARY dll +EXPORTS + hello + number diff --git a/tests/run-make/msvc-wholearchive/rmake.rs b/tests/run-make/msvc-wholearchive/rmake.rs new file mode 100644 index 00000000000..98586fd8cc8 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/rmake.rs @@ -0,0 +1,52 @@ +//! This is a regression test for #129020 +//! It ensures we can use `/WHOLEARCHIVE` to link a rust staticlib into DLL +//! using the MSVC linker + +//@ only-msvc +// Reason: this is testing the MSVC linker + +use std::path::PathBuf; + +use run_make_support::{cc, cmd, env_var, extra_c_flags, rustc}; + +fn main() { + // Build the staticlib + rustc().crate_type("staticlib").input("static.rs").output("static.lib").run(); + // Build an empty object to pass to the linker. + cc().input("c.c").output("c.obj").args(["-c"]).run(); + + // Find the C toolchain's linker. + let mut linker = PathBuf::from(env_var("CC")); + let linker_flavour = if linker.file_stem().is_some_and(|s| s == "cl") { + linker.set_file_name("link.exe"); + "msvc" + } else if linker.file_stem().is_some_and(|s| s == "clang-cl") { + linker.set_file_name("lld-link.exe"); + "llvm" + } else { + panic!("unknown C toolchain"); + }; + + // As a sanity check, make sure this works without /WHOLEARCHIVE. + // Otherwise the actual test failure may be caused by something else. + cmd(&linker) + .args(["c.obj", "./static.lib", "-dll", "-def:dll.def", "-out:dll.dll"]) + .args(extra_c_flags()) + .run(); + + // FIXME(@ChrisDenton): this doesn't currently work with llvm's lld-link for other reasons. + // May need LLVM patches. + if linker_flavour == "msvc" { + // Link in the staticlib using `/WHOLEARCHIVE` and produce a DLL. + cmd(&linker) + .args([ + "c.obj", + "-WHOLEARCHIVE:./static.lib", + "-dll", + "-def:dll.def", + "-out:dll_whole_archive.dll", + ]) + .args(extra_c_flags()) + .run(); + } +} diff --git a/tests/run-make/msvc-wholearchive/static.rs b/tests/run-make/msvc-wholearchive/static.rs new file mode 100644 index 00000000000..881c8856573 --- /dev/null +++ b/tests/run-make/msvc-wholearchive/static.rs @@ -0,0 +1,9 @@ +#[no_mangle] +pub extern "C" fn hello() { + println!("Hello world!"); +} + +#[no_mangle] +pub extern "C" fn number() -> u32 { + 42 +} diff --git a/tests/run-make/remove-dir-all-race/rmake.rs b/tests/run-make/remove-dir-all-race/rmake.rs new file mode 100644 index 00000000000..03c94b76127 --- /dev/null +++ b/tests/run-make/remove-dir-all-race/rmake.rs @@ -0,0 +1,62 @@ +//@ ignore-windows + +// This test attempts to make sure that running `remove_dir_all` +// doesn't result in a NotFound error one of the files it +// is deleting is deleted concurrently. +// +// The windows implementation for `remove_dir_all` is significantly +// more complicated, and has not yet been brought up to par with +// the implementation on other platforms, so this test is marked as +// `ignore-windows` until someone more expirenced with windows can +// sort that out. + +use std::fs::remove_dir_all; +use std::path::Path; +use std::thread; +use std::time::Duration; + +use run_make_support::rfs::{create_dir, write}; +use run_make_support::run_in_tmpdir; + +fn main() { + let mut race_happened = false; + run_in_tmpdir(|| { + for i in 0..150 { + create_dir("outer"); + create_dir("outer/inner"); + write("outer/inner.txt", b"sometext"); + + thread::scope(|scope| { + let t1 = scope.spawn(|| { + thread::sleep(Duration::from_nanos(i)); + remove_dir_all("outer").unwrap(); + }); + + let race_happened_ref = &race_happened; + let t2 = scope.spawn(|| { + let r1 = remove_dir_all("outer/inner"); + let r2 = remove_dir_all("outer/inner.txt"); + if r1.is_ok() && r2.is_err() { + race_happened = true; + } + }); + }); + + assert!(!Path::new("outer").exists()); + + // trying to remove a nonexistant top-level directory should + // still result in an error. + let Err(err) = remove_dir_all("outer") else { + panic!("removing nonexistant dir did not result in an error"); + }; + assert_eq!(err.kind(), std::io::ErrorKind::NotFound); + } + }); + if !race_happened { + eprintln!( + "WARNING: multithreaded deletion never raced, \ + try increasing the number of attempts or \ + adjusting the sleep timing" + ); + } +} diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs deleted file mode 100644 index ea4997fab80..00000000000 --- a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Checks the `compress-debug-sections` option on rust-lld. - -//@ needs-rust-lld -//@ only-linux -//@ ignore-cross-compile - -// FIXME: This test isn't comprehensive and isn't covering all possible combinations. - -use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; - -fn check_compression(compression: &str, to_find: &str) { - run_in_tmpdir(|| { - let out = rustc() - .arg("-Zlinker-features=+lld") - .arg("-Clink-self-contained=+linker") - .arg("-Zunstable-options") - .arg("-Cdebuginfo=full") - .link_arg(&format!("-Wl,--compress-debug-sections={compression}")) - .input("main.rs") - .run_unchecked(); - let stderr = out.stderr_utf8(); - if stderr.is_empty() { - llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find); - } else { - assert_contains( - stderr, - format!( - "LLVM was not built with LLVM_ENABLE_{to_find} \ - or did not find {compression} at build time" - ), - ); - } - }); -} - -fn main() { - check_compression("zlib", "ZLIB"); - check_compression("zstd", "ZSTD"); -} diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile deleted file mode 100644 index 3c88ec34f43..00000000000 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -include ../tools.mk - -#only-x86_64-fortanix-unknown-sgx - -# For cargo setting -export RUSTC := $(RUSTC_ORIGINAL) -export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) -# We need to be outside of 'src' dir in order to run cargo -export WORK_DIR := $(TMPDIR) -export TEST_DIR := $(shell pwd) - -## clean up unused env variables which might cause harm. -unexport RUSTC_LINKER -unexport RUSTC_BOOTSTRAP -unexport RUST_BUILD_STAGE -unexport RUST_TEST_THREADS -unexport RUST_TEST_TMPDIR -unexport AR -unexport CC -unexport CXX - -all: - bash script.sh diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs new file mode 100644 index 00000000000..130781a4293 --- /dev/null +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs @@ -0,0 +1,96 @@ +// ignore-tidy-linelength +// Reason: intel.com link + +// This security test checks that the disassembled form of certain symbols +// is "hardened" - that means, the assembly instructions match a pattern that +// mitigate potential Load Value Injection vulnerabilities. +// To do so, a test crate is compiled, and certain symbols are found, disassembled +// and checked one by one. +// See https://github.com/rust-lang/rust/pull/77008 + +// On load value injection: +// https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/load-value-injection.html + +//@ only-x86_64-fortanix-unknown-sgx + +use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target}; + +fn main() { + let main_dir = cwd(); + set_current_dir("enclave"); + // HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. + // These come from the top-level Rust workspace, that this crate is not a + // member of, but Cargo tries to load the workspace `Cargo.toml` anyway. + cmd("cargo") + .env("RUSTC_BOOTSTRAP", "1") + .arg("-v") + .arg("run") + .arg("--target") + .arg(target()) + .run(); + set_current_dir(&main_dir); + // Rust has various ways of adding code to a binary: + // - Rust code + // - Inline assembly + // - Global assembly + // - C/C++ code compiled as part of Rust crates + // For those different kinds, we do have very small code examples that should be + // mitigated in some way. Mostly we check that ret instructions should no longer be present. + check("unw_getcontext", "unw_getcontext.checks"); + check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks"); + + check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks"); + + check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks"); + + check("cc_plus_one_c", "cc_plus_one_c.checks"); + check("cc_plus_one_c_asm", "cc_plus_one_c_asm.checks"); + check("cc_plus_one_cxx", "cc_plus_one_cxx.checks"); + check("cc_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks"); + check("cc_plus_one_asm", "cc_plus_one_asm.checks"); + + check("cmake_plus_one_c", "cmake_plus_one_c.checks"); + check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks"); + check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks"); + check("cmake_plus_one_cxx", "cmake_plus_one_cxx.checks"); + check("cmake_plus_one_cxx_asm", "cmake_plus_one_cxx_asm.checks"); + check("cmake_plus_one_cxx_global_asm", "cmake_plus_one_cxx_global_asm.checks"); + check("cmake_plus_one_asm", "cmake_plus_one_asm.checks"); +} + +fn check(func_re: &str, mut checks: &str) { + let dump = llvm_objdump() + .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave") + .args(&["--syms", "--demangle"]) + .run() + .stdout_utf8(); + let re = regex::Regex::new(&format!("[[:blank:]]+{func_re}")).unwrap(); + let func = re.find_iter(&dump).map(|m| m.as_str().trim()).collect::<Vec<&str>>().join(","); + assert!(!func.is_empty()); + let dump = llvm_objdump() + .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave") + .args(&["--demangle", &format!("--disassemble-symbols={func}")]) + .run() + .stdout_utf8(); + let dump = dump.as_bytes(); + + // Unique case, must succeed at one of two possible tests. + // This is because frame pointers are optional, and them being enabled requires + // an additional `popq` in the pattern checking file. + if func_re == "std::io::stdio::_print::[[:alnum:]]+" { + let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked(); + if !output.status().success() { + checks = "print.without_frame_pointers.checks"; + llvm_filecheck().stdin(&dump).patterns(checks).run(); + } + } else { + llvm_filecheck().stdin(&dump).patterns(checks).run(); + } + if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"] + .contains(&func_re) + { + // The assembler cannot avoid explicit `ret` instructions. Sequences + // of `shlq $0x0, (%rsp); lfence; retq` are used instead. + llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run(); + } +} diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh deleted file mode 100644 index a7c4ae13ecb..00000000000 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -set -exuo pipefail - -function build { - CRATE=enclave - - mkdir -p "${WORK_DIR}" - pushd "${WORK_DIR}" - rm -rf "${CRATE}" - cp -a "${TEST_DIR}"/enclave . - pushd $CRATE - echo "${WORK_DIR}" - # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. - # These come from the top-level Rust workspace, that this crate is not a - # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. - env RUSTC_BOOTSTRAP=1 - cargo -v run --target "${TARGET}" - popd - popd -} - -function check { - local func_re="$1" - local checks="${TEST_DIR}/$2" - local asm="" - local objdump="${LLVM_BIN_DIR}/llvm-objdump" - local filecheck="${LLVM_BIN_DIR}/FileCheck" - local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave - - asm=$(mktemp) - func="$(${objdump} --syms --demangle "${enclave}" | \ - grep --only-matching -E "[[:blank:]]+${func_re}\$" | \ - sed -e 's/^[[:space:]]*//' )" - ${objdump} --disassemble-symbols="${func}" --demangle \ - "${enclave}" > "${asm}" - ${filecheck} --input-file "${asm}" "${checks}" - - if [ "${func_re}" != "rust_plus_one_global_asm" ] && - [ "${func_re}" != "cmake_plus_one_c_global_asm" ] && - [ "${func_re}" != "cmake_plus_one_cxx_global_asm" ]; then - # The assembler cannot avoid explicit `ret` instructions. Sequences - # of `shlq $0x0, (%rsp); lfence; retq` are used instead. - # https://www.intel.com/content/www/us/en/developer/articles/technical/ - # software-security-guidance/technical-documentation/load-value-injection.html - ${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}" - fi -} - -build - -check "unw_getcontext" unw_getcontext.checks -check "__libunwind_Registers_x86_64_jumpto" jumpto.checks -check 'std::io::stdio::_print::[[:alnum:]]+' print.with_frame_pointers.checks || - check 'std::io::stdio::_print::[[:alnum:]]+' print.without_frame_pointers.checks -check rust_plus_one_global_asm rust_plus_one_global_asm.checks - -check cc_plus_one_c cc_plus_one_c.checks -check cc_plus_one_c_asm cc_plus_one_c_asm.checks -check cc_plus_one_cxx cc_plus_one_cxx.checks -check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks -check cc_plus_one_asm cc_plus_one_asm.checks - -check cmake_plus_one_c cmake_plus_one_c.checks -check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks -check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks -check cmake_plus_one_cxx cmake_plus_one_cxx.checks -check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks -check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks -check cmake_plus_one_asm cmake_plus_one_asm.checks diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml index 82bd34ed274..92846f8e01d 100644 --- a/tests/rustdoc-gui/target.goml +++ b/tests/rustdoc-gui/target.goml @@ -11,7 +11,7 @@ define-function: ( [theme, background, border], block { call-function: ("switch-theme", {"theme": |theme|}) - assert-css: ("#method\.a_method:target", { + wait-for-css: ("#method\.a_method:target", { "background-color": |background|, "border-right": "3px solid " + |border|, }) diff --git a/tests/rustdoc-js-std/exact-case.js b/tests/rustdoc-js-std/exact-case.js new file mode 100644 index 00000000000..d9faff22fff --- /dev/null +++ b/tests/rustdoc-js-std/exact-case.js @@ -0,0 +1,7 @@ +const EXPECTED = { + 'query': 'Copy', + 'others': [ + { 'path': 'std::marker', 'name': 'Copy' }, + { 'path': 'std::fs', 'name': 'copy' }, + ], +} diff --git a/tests/rustdoc/anchors.no_type_anchor2.html b/tests/rustdoc/anchors.no_type_anchor2.html index 71e93990e29..9127104ded4 100644 --- a/tests/rustdoc/anchors.no_type_anchor2.html +++ b/tests/rustdoc/anchors.no_type_anchor2.html @@ -1 +1 @@ -<section id="associatedtype.Y" class="associatedtype"><h4 class="code-header">pub type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file +<section id="associatedtype.Y" class="associatedtype"><a class="src rightside" href="../src/foo/anchors.rs.html#45">source</a><h4 class="code-header">pub type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file diff --git a/tests/rustdoc/assoc-type-source-link.rs b/tests/rustdoc/assoc-type-source-link.rs new file mode 100644 index 00000000000..34b156b9649 --- /dev/null +++ b/tests/rustdoc/assoc-type-source-link.rs @@ -0,0 +1,26 @@ +// This test ensures that the source links are generated for impl associated types. + +#![crate_name = "foo"] +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +//@ has 'foo/struct.Bar.html' +pub struct Bar; + +impl Bar { + //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a' 'source' + //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a/@href' \ + // '../src/foo/assoc-type-source-link.rs.html#14' + pub type Y = u8; +} + +pub trait Foo { + type Z; +} + +impl Foo for Bar { + //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a' 'source' + //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a/@href' \ + // '../src/foo/assoc-type-source-link.rs.html#25' + type Z = u8; +} diff --git a/tests/rustdoc/doc-hidden-crate.rs b/tests/rustdoc/doc-hidden-crate.rs new file mode 100644 index 00000000000..dac557107a9 --- /dev/null +++ b/tests/rustdoc/doc-hidden-crate.rs @@ -0,0 +1,27 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/126796>. +// `doc(hidden)` should still be able to hide extern crates, only the local crates +// cannot be hidden because we still need to generate its `index.html` file. + +#![crate_name = "foo"] +#![doc(hidden)] + +//@ has 'foo/index.html' +// First we check that the page contains the crate name (`foo`). +//@ has - '//*' 'foo' +// But doesn't contain any of the other items. +//@ !has - '//*' 'other' +//@ !has - '//*' 'marker' +//@ !has - '//*' 'PhantomData' + +#[doc(inline)] +pub use std as other; + +#[doc(inline)] +pub use std::marker; + +#[doc(inline)] +pub use std::marker::PhantomData; + +//@ !has - '//*' 'myself' +#[doc(inline)] +pub use crate as myself; diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index 4b2fb786a89..b15e996f929 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -16,3 +16,20 @@ pub trait Bar {} //@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)' #[doc(fake_variadic)] impl<U: Foo> Bar for (U,) {} + +pub trait Baz<T> { fn baz(&self) -> T { todo!() } } + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3C(T,)%3E-for-%5BT;+1%5D"]/h3' 'impl<T> Baz<(T₁, T₂, …, Tₙ)> for [T; N]' +#[doc(fake_variadic)] +impl<T> Baz<(T,)> for [T; 1] {} + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3C%5BT;+1%5D%3E-for-(T,)"]/h3' 'impl<T> Baz<[T; N]> for (T₁, T₂, …, Tₙ)' +#[doc(fake_variadic)] +impl<T> Baz<[T; 1]> for (T,) {} + +//@ has foo/trait.Baz.html +//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)' +#[doc(fake_variadic)] +impl<T> Baz<T> for (T,) {} diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 5fcff74064a..442f9d72c3f 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -117,4 +117,11 @@ pub fn skipped_because_of_annotation<'a>(dcx: DiagCtxtHandle<'a>) { fn f(_x: impl Into<DiagMessage>, _y: impl Into<SubdiagMessage>) {} fn g() { f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example); + f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); + //~^ ERROR diagnostics should be created using translatable messages + f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); + //~^ ERROR diagnostics should be created using translatable messages + f("untranslatable diagnostic", "untranslatable diagnostic"); + //~^ ERROR diagnostics should be created using translatable messages + //~^^ ERROR diagnostics should be created using translatable messages } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 669324ce5d4..36dd3cf4be7 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:43:9 + --> $DIR/diagnostics.rs:43:31 | LL | Diag::new(dcx, level, "untranslatable diagnostic") - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:7:9 @@ -11,16 +11,16 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:64:14 + --> $DIR/diagnostics.rs:64:19 | LL | diag.note("untranslatable diagnostic"); - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:85:14 + --> $DIR/diagnostics.rs:85:19 | LL | diag.note("untranslatable diagnostic"); - | ^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls --> $DIR/diagnostics.rs:99:21 @@ -41,10 +41,34 @@ LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:102:21 + --> $DIR/diagnostics.rs:102:32 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:120:7 + | +LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:122:50 + | +LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:124:7 + | +LL | f("untranslatable diagnostic", "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: diagnostics should be created using translatable messages + --> $DIR/diagnostics.rs:124:36 + | +LL | f("untranslatable diagnostic", "untranslatable diagnostic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5e3f2557566..5449c09d35a 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -17,12 +17,14 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use mir::{mono::Instance, TerminatorKind::*}; +use std::io::Write; +use std::ops::ControlFlow; + +use mir::mono::Instance; +use mir::TerminatorKind::*; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; -use std::io::Write; -use std::ops::ControlFlow; const CRATE_NAME: &str = "input"; @@ -33,7 +35,7 @@ fn test_stable_mir() -> ControlFlow<()> { // Get all items and split generic vs monomorphic items. let (generic, mono): (Vec<_>, Vec<_>) = items.into_iter().partition(|item| item.requires_monomorphization()); - assert_eq!(mono.len(), 3, "Expected 3 mono functions"); + assert_eq!(mono.len(), 4, "Expected 3 mono functions"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index ca78604edd8..d37e793d989 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -40,9 +40,10 @@ //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch //@[loongarch64] min-llvm-version: 18 -//@ revisions: wasm -//@[wasm] compile-flags: --target wasm32-unknown-unknown -//@[wasm] needs-llvm-components: webassembly +//FIXME: wasm is disabled due to <https://github.com/rust-lang/rust/issues/115666>. +//FIXME @ revisions: wasm +//FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown +//FIXME @[wasm] needs-llvm-components: webassembly //@ revisions: wasip1 //@[wasip1] compile-flags: --target wasm32-wasip1 //@[wasip1] needs-llvm-components: webassembly diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr index 9e37bb4c203..9d84d2666b3 100644 --- a/tests/ui/asm/aarch64/type-check-3.stderr +++ b/tests/ui/asm/aarch64/type-check-3.stderr @@ -95,7 +95,7 @@ error: type `i128` cannot be used with this register class LL | asm!("{}", in(reg) 0i128); | ^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `float64x2_t` cannot be used with this register class --> $DIR/type-check-3.rs:75:28 @@ -103,7 +103,7 @@ error: type `float64x2_t` cannot be used with this register class LL | asm!("{}", in(reg) f64x2); | ^^^^^ | - = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64 error: type `Simd256bit` cannot be used with this register class --> $DIR/type-check-3.rs:77:29 @@ -111,7 +111,7 @@ error: type `Simd256bit` cannot be used with this register class 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 + = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, f128, i8x8, i16x4, i32x2, i64x1, f16x4, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: incompatible types for asm inout argument --> $DIR/type-check-3.rs:88:33 diff --git a/tests/ui/asm/aarch64/type-f16.rs b/tests/ui/asm/aarch64/type-f16.rs new file mode 100644 index 00000000000..e62d8130c93 --- /dev/null +++ b/tests/ui/asm/aarch64/type-f16.rs @@ -0,0 +1,25 @@ +//@ only-aarch64 +//@ run-pass +//@ needs-asm-support + +#![feature(f16)] + +use std::arch::asm; + +#[inline(never)] +pub fn f32_to_f16_asm(a: f32) -> f16 { + let ret: f16; + unsafe { + asm!( + "fcvt {ret:h}, {a:s}", + a = in(vreg) a, + ret = lateout(vreg) ret, + options(nomem, nostack), + ); + } + ret +} + +fn main() { + assert_eq!(f32_to_f16_asm(1.0 as f32), 1.0); +} diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.rs b/tests/ui/asm/naked-with-invalid-repr-attr.rs new file mode 100644 index 00000000000..687fe1ad73d --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.rs @@ -0,0 +1,48 @@ +//@ needs-asm-support +#![feature(naked_functions)] +#![feature(fn_align)] +#![crate_type = "lib"] +use std::arch::asm; + +#[repr(C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example1() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(transparent)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example2() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(align(16), C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example3() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +// note: two errors because of packed and C +#[repr(C, packed)] +//~^ ERROR attribute should be applied to a struct or union [E0517] +//~| ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example4() { + //~^ NOTE not a struct, enum, or union + //~| NOTE not a struct or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(u8)] +//~^ ERROR attribute should be applied to an enum [E0517] +#[naked] +extern "C" fn example5() { + //~^ NOTE not an enum + unsafe { asm!("", options(noreturn)) } +} diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.stderr b/tests/ui/asm/naked-with-invalid-repr-attr.stderr new file mode 100644 index 00000000000..3740f17a9dc --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.stderr @@ -0,0 +1,77 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:7:8 + | +LL | #[repr(C)] + | ^ +... +LL | / extern "C" fn example1() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:15:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +... +LL | / extern "C" fn example2() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:23:19 + | +LL | #[repr(align(16), C)] + | ^ +... +LL | / extern "C" fn example3() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:8 + | +LL | #[repr(C, packed)] + | ^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:11 + | +LL | #[repr(C, packed)] + | ^^^^^^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct or union + +error[E0517]: attribute should be applied to an enum + --> $DIR/naked-with-invalid-repr-attr.rs:42:8 + | +LL | #[repr(u8)] + | ^^ +... +LL | / extern "C" fn example5() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not an enum + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index a495e94bd9a..cf5d8f614dd 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when computing predicates of `Foo` LL | struct Foo { | ^^^^^^^^^^ | -note: ...which requires computing predicates of `Foo`... - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ note: ...which requires computing inferred outlives predicates of `Foo`... --> $DIR/cycle-iat-inside-of-adt.rs:7:1 | diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr index e7292c08ebd..e97a5df9d49 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when computing predicates of `user` LL | fn user<T>() where S<T>::P: std::fmt::Debug {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires computing predicates of `user`... - --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 - | -LL | fn user<T>() where S<T>::P: std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires computing explicit predicates of `user`... --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 | diff --git a/tests/ui/attributes/rustc_pub_transparent.rs b/tests/ui/attributes/rustc_pub_transparent.rs new file mode 100644 index 00000000000..4508fa39baf --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.rs @@ -0,0 +1,25 @@ +#![feature(rustc_attrs, transparent_unions)] + +#[rustc_pub_transparent] +#[repr(transparent)] +union E<T: Copy> { + value: T, + uninit: (), +} + +#[repr(transparent)] +#[rustc_pub_transparent] +struct S<T>(T); + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +#[repr(C)] +struct S1 { + A: u8, +} + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +struct S2<T> { + value: T, +} + +fn main() {} diff --git a/tests/ui/attributes/rustc_pub_transparent.stderr b/tests/ui/attributes/rustc_pub_transparent.stderr new file mode 100644 index 00000000000..1d1f9437cb2 --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.stderr @@ -0,0 +1,23 @@ +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:14:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[repr(C)] +LL | / struct S1 { +LL | | A: u8, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:20:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / struct S2<T> { +LL | | value: T, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: aborting due to 2 previous errors + diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 54d8f26f4ea..5f0347bdb4d 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -30,9 +30,9 @@ note: the lifetime `'c` as defined here... 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 + --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24 | -LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { +LL | fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); | ^^ error[E0308]: method not compatible with trait @@ -44,16 +44,15 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)` found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... - --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + --> $DIR/regions-bound-missing-bound-in-impl.rs:12:24 | -LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { +LL | fn wrong_bound1<'b,'c,'d:'a+'b>(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>) { | ^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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 diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 520cffc4b02..9b6448fe5a0 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 239 more = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index d780e04e729..56423d8c307 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -285,7 +285,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 29 warnings emitted diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index cb718ca160f..2538fc0361c 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` +error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); @@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | | | 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::<_, _>}` + = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::<T>::map` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs new file mode 100644 index 00000000000..19723bee4d4 --- /dev/null +++ b/tests/ui/coercion/cast-higher-ranked-unsafe-fn-ptr.rs @@ -0,0 +1,14 @@ +//@ check-pass + +fn higher_ranked_fndef(ctx: &mut ()) {} + +fn test(higher_ranked_fnptr: fn(&mut ())) { + fn as_unsafe<T>(_: unsafe fn(T)) {} + + // Make sure that we can cast higher-ranked fn items and pointers to + // a non-higher-ranked target. + as_unsafe(higher_ranked_fndef); + as_unsafe(higher_ranked_fnptr); +} + +fn main() {} diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs index e07fa78463c..cdfeb9c434e 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs @@ -5,7 +5,9 @@ #![feature(with_negative_coherence)] trait Trait {} impl<const N: u8> Trait for [(); N] {} +//~^ ERROR: mismatched types impl<const N: i8> Trait for [(); N] {} //~^ ERROR: conflicting implementations of trait `Trait` +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr index 2087be8e711..d65450845bc 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr @@ -1,11 +1,25 @@ error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` - --> $DIR/generic_const_type_mismatch.rs:8:1 + --> $DIR/generic_const_type_mismatch.rs:9:1 | LL | impl<const N: u8> Trait for [(); N] {} | ----------------------------------- first implementation here +LL | LL | impl<const N: i8> Trait for [(); N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/generic_const_type_mismatch.rs:7:34 + | +LL | impl<const N: u8> Trait for [(); N] {} + | ^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/generic_const_type_mismatch.rs:9:34 + | +LL | impl<const N: i8> Trait for [(); N] {} + | ^ expected `usize`, found `i8` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs index 569e57fa326..401267a0f16 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs @@ -4,11 +4,11 @@ #![allow(incomplete_features, unstable_features)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>() where - Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, + Dst: TransmuteFrom<Src, Context, ASSUME>, //~^ ERROR trait takes at most 2 generic arguments but 3 generic arguments were supplied { } diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr index 5c04c4c9d5b..96716685614 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr @@ -1,8 +1,8 @@ error[E0107]: trait takes at most 2 generic arguments but 3 generic arguments were supplied --> $DIR/transmutable-ice-110969.rs:11:14 | -LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, - | ^^^^^^^^^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument +LL | Dst: TransmuteFrom<Src, Context, ASSUME>, + | ^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument | | | expected at most 2 generic arguments diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index cc2ff9b8dea..c4e74596e9f 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -7,6 +7,7 @@ trait Q { impl<const N: u64> Q for [u8; N] { //~^ ERROR: the constant `N` is not of type `usize` + //~| ERROR: mismatched types const ASSOC: usize = 1; } diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 5c8d9c90363..21ec8f0768c 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -5,7 +5,7 @@ LL | impl<const N: u64> Q for [u8; N] { | ^^^^^^^ expected `usize`, found `u64` error: the constant `13` is not of type `u64` - --> $DIR/bad-subst-const-kind.rs:13:24 + --> $DIR/bad-subst-const-kind.rs:14:24 | LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { | ^^^^^^^^ expected `u64`, found `usize` @@ -18,5 +18,12 @@ LL | impl<const N: u64> Q for [u8; N] { | | | unsatisfied trait bound introduced here -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/bad-subst-const-kind.rs:8:31 + | +LL | impl<const N: u64> Q for [u8; N] { + | ^ expected `usize`, found `u64` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs new file mode 100644 index 00000000000..f9730cf8566 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested.rs @@ -0,0 +1,21 @@ +//@ check-pass + +// This is a regression test for #128016. + +macro_rules! len_inner { + () => { + BAR + }; +} + +macro_rules! len { + () => { + len_inner!() + }; +} + +const BAR: usize = 0; + +fn main() { + let val: [bool; len!()] = []; +} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs new file mode 100644 index 00000000000..f123e55c028 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-param.rs @@ -0,0 +1,13 @@ +//@ check-pass + +macro_rules! len { + ($x:ident) => { + $x + }; +} + +fn bar<const N: usize>() { + let val: [bool; len!(N)] = [true; N]; +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs new file mode 100644 index 00000000000..f218caac0cf --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.rs @@ -0,0 +1,13 @@ +// This is a regression test for #128016. + +macro_rules! len { + () => { + target + //~^ ERROR cannot find value `target` + }; +} + +fn main() { + let val: [str; len!()] = []; + //~^ ERROR the size for values +} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr new file mode 100644 index 00000000000..ab289e5a6b7 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr @@ -0,0 +1,24 @@ +error[E0425]: cannot find value `target` in this scope + --> $DIR/trivial-const-arg-macro-res-error.rs:5:9 + | +LL | target + | ^^^^^^ not found in this scope +... +LL | let val: [str; len!()] = []; + | ------ in this macro invocation + | + = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/trivial-const-arg-macro-res-error.rs:11:14 + | +LL | let val: [str; len!()] = []; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +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/const-generics/early/trivial-const-arg-macro.rs b/tests/ui/const-generics/early/trivial-const-arg-macro.rs new file mode 100644 index 00000000000..a19d9abfdcb --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro.rs @@ -0,0 +1,15 @@ +//@ check-pass + +// This is a regression test for #128016. + +macro_rules! len { + () => { + BAR + }; +} + +const BAR: usize = 0; + +fn main() { + let val: [bool; len!()] = []; +} diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs index 8e5e23b2337..a45deabbb0f 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -8,6 +8,7 @@ trait Q { impl<const N: u64> Q for [u8; N] {} //~^ ERROR not all trait items implemented //~| ERROR the constant `N` is not of type `usize` +//~| ERROR mismatched types pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} //~^ ERROR the constant `13` is not of type `u64` diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index e03580ec007..68870a8d38d 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -14,7 +14,7 @@ LL | impl<const N: u64> Q for [u8; N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation error: the constant `13` is not of type `u64` - --> $DIR/type_mismatch.rs:12:26 + --> $DIR/type_mismatch.rs:13:26 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ^^^^^^^^ expected `u64`, found `usize` @@ -28,14 +28,20 @@ LL | impl<const N: u64> Q for [u8; N] {} | unsatisfied trait bound introduced here error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:12:20 + --> $DIR/type_mismatch.rs:13:20 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:8:31 + | +LL | impl<const N: u64> Q for [u8; N] {} + | ^ expected `usize`, found `u64` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0046, E0308. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 8b7ee577569..05a3487ffca 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -14,8 +14,8 @@ mod v20 { //~^ ERROR cannot find value `v8` in this scope //~| ERROR cannot find function `v6` in this scope pub struct v17<const v10: usize, const v7: v11> { - //~^ WARN type `v17` should have an upper camel case name - //~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter + //~^ WARN type `v17` should have an upper camel case name + //~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter _p: (), } @@ -25,10 +25,10 @@ mod v20 { } impl<const v10: usize> v17<v10, v2> { - //~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0} - //~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0} + //~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} pub const fn v21() -> v18 { - //~^ ERROR cannot find type `v18` in this scope + //~^ ERROR cannot find type `v18` in this scope v18 { _p: () } //~^ ERROR cannot find struct, variant or union type `v18` in this scope } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 15d3c472585..39f022fbee9 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0} +error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl<const v10: usize> v17<v10, v2> { | ^^ -error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0} +error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl<const v10: usize> v17<v10, v2> { diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index 59b77c678e8..a9b297ffb62 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -2,108 +2,108 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } +fn foo<const W: usize, const H: usize>(v: [[u32; H + 1]; W]) -> [[u32; W + 1]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { - //~^ ERROR the constant `W` is not of type `usize` - unsafe { - std::mem::transmute(v) - //~^ ERROR the constant `W` is not of type `usize` - } + //~^ ERROR: the constant `W` is not of type `usize` + //~| ERROR: mismatched types + //~| ERROR: mismatched types + unsafe { + std::mem::transmute(v) + //~^ ERROR: the constant `W` is not of type `usize` + } } fn baz<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 8888888] { - unsafe { - std::mem::transmute(v) - //~^ ERROR cannot transmute - } + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } } -fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn transpose<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { - unsafe { - std::mem::transmute(v) - } + unsafe { std::mem::transmute(v) } } fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } -fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn coagulate<const W: usize, const H: usize>(v: [u32; H * W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn flatten_3d<const W: usize, const H: usize, const D: usize>( - v: [[[u32; D]; H]; W] + v: [[[u32; D]; H]; W], ) -> [u32; D * W * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn flatten_somewhat<const W: usize, const H: usize, const D: usize>( - v: [[[u32; D]; H]; W] + v: [[[u32; D]; H]; W], ) -> [[u32; D * W]; H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } -fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } +fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8; 1]; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn transpose_with_const<const W: usize, const H: usize>( - v: [[u32; 2 * H]; W + W] + v: [[u32; 2 * H]; W + W], ) -> [[u32; W + W]; 2 * H] { - unsafe { - std::mem::transmute(v) - //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types - } + unsafe { + std::mem::transmute(v) + //~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types + } } fn main() {} diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index b40fb23c331..124fbee8850 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -5,119 +5,132 @@ LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { | ^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:7:5 + --> $DIR/transmute-fail.rs:7:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1]) - = note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1]) + = note: source type: `[[u32; H + 1]; W]` (size can vary because of [u32; H + 1]) + = note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1]) error: the constant `W` is not of type `usize` - --> $DIR/transmute-fail.rs:15:5 + --> $DIR/transmute-fail.rs:17:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:22:5 + --> $DIR/transmute-fail.rs:24:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:29:5 + --> $DIR/transmute-fail.rs:31:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:36:5 + --> $DIR/transmute-fail.rs:38:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:49:5 + --> $DIR/transmute-fail.rs:49:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[u32; W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:56:5 + --> $DIR/transmute-fail.rs:56:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[u32; H*W]` (this type does not have a fixed size) + = note: source type: `[u32; H * W]` (this type does not have a fixed size) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:65:5 + --> $DIR/transmute-fail.rs:65:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:74:5 + --> $DIR/transmute-fail.rs:74:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D]) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:81:5 + --> $DIR/transmute-fail.rs:81:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u16; L]` (this type does not have a fixed size) = note: target type: `[u8; L * 2]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:88:5 + --> $DIR/transmute-fail.rs:88:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u8; L * 2]` (this type does not have a fixed size) = note: target type: `[u16; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:95:5 + --> $DIR/transmute-fail.rs:95:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[u8; L]` (this type does not have a fixed size) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:104:5 + --> $DIR/transmute-fail.rs:104:9 | -LL | std::mem::transmute(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) -error: aborting due to 14 previous errors +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:53 + | +LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:67 + | +LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error: aborting due to 16 previous errors -For more information about this error, try `rustc --explain E0512`. +Some errors have detailed explanations: E0308, E0512. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs index 8187c785cd1..9c7217cd83e 100644 --- a/tests/ui/const-generics/type_mismatch.rs +++ b/tests/ui/const-generics/type_mismatch.rs @@ -1,10 +1,12 @@ fn foo<const N: usize>() -> [u8; N] { bar::<N>() //~^ ERROR the constant `N` is not of type `u8` + //~| ERROR: mismatched types } fn bar<const N: u8>() -> [u8; N] {} //~^ ERROR the constant `N` is not of type `usize` +//~| 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 index d1bb5c1242f..77e9f5e2b44 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `N` is not of type `usize` - --> $DIR/type_mismatch.rs:6:26 + --> $DIR/type_mismatch.rs:7:26 | LL | fn bar<const N: u8>() -> [u8; N] {} | ^^^^^^^ expected `usize`, found `u8` @@ -11,19 +11,31 @@ LL | bar::<N>() | ^ expected `u8`, found `usize` | note: required by a const generic parameter in `bar` - --> $DIR/type_mismatch.rs:6:8 + --> $DIR/type_mismatch.rs:7:8 | LL | fn bar<const N: u8>() -> [u8; N] {} | ^^^^^^^^^^^ required by this const generic parameter in `bar` error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:6:26 + --> $DIR/type_mismatch.rs:7:26 | LL | fn bar<const N: u8>() -> [u8; N] {} | --- ^^^^^^^ expected `[u8; N]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::<N>() + | ^ expected `u8`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:7:31 + | +LL | fn bar<const N: u8>() -> [u8; N] {} + | ^ expected `usize`, found `u8` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.rs b/tests/ui/consts/const-eval/const_fn_target_feature.rs index ee669abb51e..8db41ba11c0 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature.rs @@ -1,6 +1,7 @@ //@ only-x86_64 // Set the base cpu explicitly, in case the default has been changed. //@ compile-flags: -C target-cpu=x86-64 -C target-feature=+ssse3 +//@ check-pass #![crate_type = "lib"] @@ -9,7 +10,8 @@ const A: () = unsafe { ssse3_fn() }; // error (avx2 not enabled at compile time) const B: () = unsafe { avx2_fn() }; -//~^ ERROR evaluation of constant value failed +// FIXME: currently we do not detect this UB, since we don't want the result of const-eval +// to depend on `tcx.sess` which can differ between crates in a crate graph. #[target_feature(enable = "ssse3")] const unsafe fn ssse3_fn() {} diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.stderr b/tests/ui/consts/const-eval/const_fn_target_feature.stderr deleted file mode 100644 index d3a00b57ebb..00000000000 --- a/tests/ui/consts/const-eval/const_fn_target_feature.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_target_feature.rs:11:24 - | -LL | const B: () = unsafe { avx2_fn() }; - | ^^^^^^^^^ calling a function that requires unavailable target features: avx2 - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs index deed09e4b2a..8ddfe61943c 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs @@ -7,7 +7,9 @@ #[cfg(target_feature = "simd128")] compile_error!("simd128 target feature should be disabled"); -// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 +// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. +// (It can still lead to a runtime error though so we'd be in our right to abort execution, +// just not to declare it UB.) const A: () = simd128_fn(); #[target_feature(enable = "simd128")] diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.rs b/tests/ui/consts/const-eval/ub-write-through-immutable.rs index 945367f1823..9860b8fde4a 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.rs +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.rs @@ -1,6 +1,5 @@ //! Ensure we catch UB due to writing through a shared reference. #![feature(const_mut_refs, const_refs_to_cell)] -#![deny(writes_through_immutable_pointer)] #![allow(invalid_reference_casting)] use std::mem; @@ -9,15 +8,15 @@ use std::cell::UnsafeCell; const WRITE_AFTER_CAST: () = unsafe { let mut x = 0; let ptr = &x as *const i32 as *mut i32; - *ptr = 0; //~ERROR: writes_through_immutable_pointer - //~^ previously accepted + *ptr = 0; //~ERROR: evaluation of constant value failed + //~| immutable }; const WRITE_AFTER_TRANSMUTE: () = unsafe { let mut x = 0; let ptr: *mut i32 = mem::transmute(&x); - *ptr = 0; //~ERROR: writes_through_immutable_pointer - //~^ previously accepted + *ptr = 0; //~ERROR: evaluation of constant value failed + //~| immutable }; // it's okay when there is interior mutability; diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr index 27eb2d2c0d1..dbcd35e0b88 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.stderr +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.stderr @@ -1,55 +1,15 @@ -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:12:5 +error[E0080]: evaluation of constant value failed + --> $DIR/ub-write-through-immutable.rs:11:5 | LL | *ptr = 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 #X <https://github.com/rust-lang/rust/issues/X> -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:19:5 +error[E0080]: evaluation of constant value failed + --> $DIR/ub-write-through-immutable.rs:18:5 | LL | *ptr = 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 #X <https://github.com/rust-lang/rust/issues/X> + | ^^^^^^^^ writing through a pointer that was derived from a shared (immutable) reference error: aborting due to 2 previous errors -Future incompatibility report: Future breakage diagnostic: -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:12:5 - | -LL | *ptr = 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 #X <https://github.com/rust-lang/rust/issues/X> -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: writing through a pointer that was derived from a shared (immutable) reference - --> $DIR/ub-write-through-immutable.rs:19:5 - | -LL | *ptr = 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 #X <https://github.com/rust-lang/rust/issues/X> -note: the lint level is defined here - --> $DIR/ub-write-through-immutable.rs:3:9 - | -LL | #![deny(writes_through_immutable_pointer)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - +For more information about this error, try `rustc --explain E0080`. 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 index c7078e46fa6..efc0a1c2fba 100644 --- 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 @@ -1,9 +1,5 @@ #![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 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 index 29fa90d611c..9cdeec159be 100644 --- 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 @@ -1,15 +1,5 @@ -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: pointers cannot be cast to integers during const eval - --> $DIR/const-extern-fn-min-const-fn.rs:7:48 + --> $DIR/const-extern-fn-min-const-fn.rs:3:48 | LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } | ^^^^^^^^^^^^ @@ -17,6 +7,5 @@ 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 +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn.rs index 57f5da8d0af..4b164767064 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn.rs @@ -17,6 +17,19 @@ const unsafe extern "C" fn bar2(val: bool) -> bool { !val } +#[allow(improper_ctypes_definitions)] +const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { + x +} + +#[allow(improper_ctypes_definitions)] +const unsafe extern "C" fn closure() -> fn() { + || {} +} + +const unsafe extern "C" fn use_float() -> f32 { + 1.0 + 1.0 +} fn main() { let a: [u8; foo1(25) as usize] = [0; 26]; @@ -32,4 +45,8 @@ fn main() { 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; + + unsize(&[0, 1, 2]); + unsafe { closure(); } + unsafe { use_float(); } } diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs index 45e8ea570ed..3a526c54dc3 100644 --- a/tests/ui/consts/const-float-bits-conv.rs +++ b/tests/ui/consts/const-float-bits-conv.rs @@ -3,8 +3,9 @@ #![feature(const_float_bits_conv)] #![feature(const_float_classify)] +#![feature(f16)] +#![feature(f128)] #![allow(unused_macro_rules)] - // Don't promote const fn nop<T>(x: T) -> T { x } @@ -28,6 +29,37 @@ fn has_broken_floats() -> bool { std::env::var("TARGET").is_ok_and(|v| v.contains("i586")) } +#[cfg(target_arch = "x86_64")] +fn f16(){ + const_assert!((1f16).to_bits(), 0x3c00); + const_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); + const_assert!((12.5f16).to_bits(), 0x4a40); + const_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); + const_assert!((1337f16).to_bits(), 0x6539); + const_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); + const_assert!((-14.25f16).to_bits(), 0xcb20); + const_assert!(f16::from_bits(0x3c00), 1.0); + const_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); + const_assert!(f16::from_bits(0x4a40), 12.5); + const_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); + const_assert!(f16::from_bits(0x5be0), 252.0); + const_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); + const_assert!(f16::from_bits(0xcb20), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u16 = f16::NAN.to_bits() ^ 0x0155; + const SIGNALING_NAN: u16 = f16::NAN.to_bits() ^ 0x02AA; + + const_assert!(f16::from_bits(QUIET_NAN).is_nan()); + const_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } +} + fn f32() { const_assert!((1f32).to_bits(), 0x3f800000); const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); @@ -88,7 +120,43 @@ fn f64() { } } +#[cfg(target_arch = "x86_64")] +fn f128() { + const_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); + const_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); + const_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + const_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); + const_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); + const_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); + const_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); + const_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); + const_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); + const_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); + const_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); + const_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); + assert_eq!(f128::from_ne_bytes(0x40094e40000000000000000000000000u128.to_ne_bytes()), 1337.0); + const_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // NOTE: These names assume `f{BITS}::NAN` is a quiet NAN and IEEE754-2008's NaN rules apply! + const QUIET_NAN: u128 = f128::NAN.to_bits() | 0x0000_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA; + const SIGNALING_NAN: u128 = f128::NAN.to_bits() ^ 0x0000_5555_5555_5555_5555_5555_5555_5555; + + const_assert!(f128::from_bits(QUIET_NAN).is_nan()); + const_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); + const_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + if !has_broken_floats() { + const_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + } +} + fn main() { + #[cfg(target_arch = "x86_64")] + { + f16(); + f128(); + } f32(); f64(); } diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr deleted file mode 100644 index e1b8154a287..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/const_fn_floating_point_arithmetic.rs:20:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.rs b/tests/ui/consts/const_fn_floating_point_arithmetic.rs deleted file mode 100644 index b0d0bc6b9f4..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.rs +++ /dev/null @@ -1,20 +0,0 @@ -// 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 deleted file mode 100644 index b5b94786ebb..00000000000 --- a/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr +++ /dev/null @@ -1,53 +0,0 @@ -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -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 <https://github.com/rust-lang/rust/issues/57241> for more information - = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_let_eq_float.rs b/tests/ui/consts/const_let_eq_float.rs index 30d839cdc2a..c9ca6b8b7ea 100644 --- a/tests/ui/consts/const_let_eq_float.rs +++ b/tests/ui/consts/const_let_eq_float.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(const_fn_floating_point_arithmetic)] - struct Foo<T>(T); struct Bar<T> { x: T } struct W(f32); diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 52d3e003f0a..8a7a0981f41 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | 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 index a97eeadd92f..fe92787aec1 100644 --- 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 @@ -1,6 +1,4 @@ //@ run-pass -#![feature(rustc_allow_const_fn_unstable)] - #![feature(rustc_attrs, staged_api)] #![stable(feature = "rust1", since = "1.0.0")] 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 index bb240fb4ad6..480b16b28a5 100644 --- 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 @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_refs_to_cell, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -25,9 +25,15 @@ 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)]` +// conformity is required +const fn bar3() -> u32 { + let x = std::cell::Cell::new(0u32); + x.get(); + //~^ ERROR const-stable function cannot use `#[feature(const_refs_to_cell)]` + //~| ERROR cannot call non-const fn + foo() + //~^ ERROR is 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")] 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 index 7ec2508ca93..019deda063c 100644 --- 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 @@ -14,30 +14,47 @@ 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 +error: const-stable function cannot use `#[feature(const_refs_to_cell)]` + --> $DIR/min_const_fn_libstd_stability.rs:31:5 | -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | ^^^^^^^^^^^^^ +LL | x.get(); + | ^ | help: if it is not part of the public API, make this function unstably const | LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } +LL | const fn bar3() -> u32 { | -help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval) | -LL + #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] -LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } +LL + #[rustc_allow_const_fn_unstable(const_refs_to_cell)] +LL | const fn bar3() -> u32 { | +error[E0015]: cannot call non-const fn `Cell::<u32>::get` in constant functions + --> $DIR/min_const_fn_libstd_stability.rs:31:7 + | +LL | x.get(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:34:5 + | +LL | foo() + | ^^^^^ + | + = 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_fn_libstd_stability.rs:39:32 + --> $DIR/min_const_fn_libstd_stability.rs:45: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 +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. 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 index 03084c8674d..f2a54b8a13d 100644 --- 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 @@ -3,7 +3,7 @@ we're apparently really bad at it", issue = "none")] -#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(const_refs_to_cell, foo, foo2)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] @@ -23,12 +23,6 @@ const unsafe fn foo2() -> u32 { 42 } // 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 } 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 index 72c1f175d1d..353b117efbc 100644 --- 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 @@ -14,30 +14,13 @@ 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 = "...")] -LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | -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)] -LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } - | - error: `foo2_gated` is not yet stable as a const fn - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:39:48 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33: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 +error: aborting due to 3 previous errors diff --git a/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr b/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr new file mode 100644 index 00000000000..6038c6d332f --- /dev/null +++ b/tests/ui/consts/precise-drop-allow-const-fn-unstable.not_allow.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time + --> $DIR/precise-drop-allow-const-fn-unstable.rs:11:24 + | +LL | pub const fn unwrap<T>(this: Option<T>) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs b/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs new file mode 100644 index 00000000000..56155e519dc --- /dev/null +++ b/tests/ui/consts/precise-drop-allow-const-fn-unstable.rs @@ -0,0 +1,17 @@ +//@ revisions: allow not_allow +//@ compile-flags: --crate-type=lib -Cinstrument-coverage -Zno-profiler-runtime +//@[allow] check-pass + +#![feature(staged_api, rustc_allow_const_fn_unstable)] +#![stable(feature = "rust_test", since = "1.0.0")] + +#[stable(feature = "rust_test", since = "1.0.0")] +#[rustc_const_stable(feature = "rust_test", since = "1.0.0")] +#[cfg_attr(allow, rustc_allow_const_fn_unstable(const_precise_live_drops))] +pub const fn unwrap<T>(this: Option<T>) -> T { +//[not_allow]~^ ERROR: cannot be evaluated + match this { + Some(x) => x, + None => panic!(), + } +} diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index d4fc1717538..ec01225c6bf 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -48,10 +48,10 @@ LL | const STATIC: &str = ""; = note: expected reference `&'static _` found reference `&_` note: the anonymous lifetime as defined here... - --> $DIR/elided-lifetime.rs:15:18 + --> $DIR/elided-lifetime.rs:16:19 | -LL | impl Bar for Foo<'_> { - | ^^ +LL | const STATIC: &str = ""; + | ^ = note: ...does not necessarily outlive the static lifetime error: aborting due to 3 previous errors diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index 8e4c27875ab..b8e2f412b49 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -30,10 +30,10 @@ LL | const STATIC: &str = ""; = note: expected reference `&_` found reference `&_` note: the anonymous lifetime as defined here... - --> $DIR/static-trait-impl.rs:8:10 + --> $DIR/static-trait-impl.rs:9:19 | -LL | impl Bar<'_> for A { - | ^^ +LL | const STATIC: &str = ""; + | ^ note: ...does not necessarily outlive the anonymous lifetime as defined here --> $DIR/static-trait-impl.rs:8:10 | diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index f3b53e331ad..257ab760ffc 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -8,11 +8,6 @@ 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 - reuse a as b { #![rustc_dummy] self } -LL + reuse a as b { #[rustc_dummy] self } - | error: aborting due to 1 previous error diff --git a/tests/ui/dst/dst-rvalue.stderr b/tests/ui/dst/dst-rvalue.stderr index 8d0a82b707d..d8c529617f7 100644 --- a/tests/ui/dst/dst-rvalue.stderr +++ b/tests/ui/dst/dst-rvalue.stderr @@ -9,6 +9,11 @@ LL | let _x: Box<str> = Box::new(*"hello world"); = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Box::<T>::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box<str> = Box::new(*"hello world"); +LL + let _x: Box<str> = Box::new("hello world"); + | error[E0277]: the size for values of type `[isize]` cannot be known at compilation time --> $DIR/dst-rvalue.rs:8:37 @@ -21,6 +26,11 @@ LL | let _x: Box<[isize]> = Box::new(*array); = help: the trait `Sized` is not implemented for `[isize]` note: required by a bound in `Box::<T>::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x: Box<[isize]> = Box::new(*array); +LL + let _x: Box<[isize]> = Box::new(array); + | error: aborting due to 2 previous errors diff --git a/tests/ui/duplicate-label-E0381-issue-129274.rs b/tests/ui/duplicate-label-E0381-issue-129274.rs new file mode 100644 index 00000000000..b2156e630c8 --- /dev/null +++ b/tests/ui/duplicate-label-E0381-issue-129274.rs @@ -0,0 +1,13 @@ +fn main() { + fn test() { + loop { + let blah: Option<String>; + if true { + blah = Some("".to_string()); + } + if let Some(blah) = blah.as_ref() { //~ ERROR E0381 + } + } + } + println!("{:?}", test()) +} diff --git a/tests/ui/duplicate-label-E0381-issue-129274.stderr b/tests/ui/duplicate-label-E0381-issue-129274.stderr new file mode 100644 index 00000000000..7f8bddb17c5 --- /dev/null +++ b/tests/ui/duplicate-label-E0381-issue-129274.stderr @@ -0,0 +1,15 @@ +error[E0381]: used binding `blah` is possibly-uninitialized + --> $DIR/duplicate-label-E0381-issue-129274.rs:8:33 + | +LL | let blah: Option<String>; + | ---- binding declared here but left uninitialized +LL | if true { +LL | blah = Some("".to_string()); + | ---- binding initialized here in some conditions +LL | } +LL | if let Some(blah) = blah.as_ref() { + | ^^^^ `blah` used here but it is possibly-uninitialized + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs new file mode 100644 index 00000000000..19b5edb620f --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +trait Trait {} + +impl dyn Trait { + const CONST: () = (); +} + +fn main() { + match () { + Trait::CONST => {} + //~^ ERROR trait objects must include the `dyn` keyword + } +} diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr new file mode 100644 index 00000000000..4446a89b63b --- /dev/null +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 + | +LL | Trait::CONST => {} + | ^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | <dyn Trait>::CONST => {} + | ++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs index 74c138af483..2713ba6ed6c 100644 --- a/tests/ui/error-codes/E0208.rs +++ b/tests/ui/error-codes/E0208.rs @@ -1,7 +1,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct Foo<'a, T> { //~ ERROR [+, o] +struct Foo<'a, T> { //~ ERROR ['a: +, T: o] t: &'a mut T, } diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr index 77b6ceae4dc..a39e93afab3 100644 --- a/tests/ui/error-codes/E0208.stderr +++ b/tests/ui/error-codes/E0208.stderr @@ -1,4 +1,4 @@ -error: [+, o] +error: ['a: +, T: o] --> $DIR/E0208.rs:4:1 | LL | struct Foo<'a, T> { diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr index 83492988479..044c1ae2dd4 100644 --- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr +++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr @@ -1,21 +1,21 @@ -warning: `extern` fn uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` fn uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:7:12 | LL | type Foo = extern "C" fn(::std::ffi::CStr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes_definitions)]` on by default -warning: `extern` block uses type `[i8 or u8 (arch dependant)]`, which is not FFI-safe +warning: `extern` block uses type `CStr`, which is not FFI-safe --> $DIR/extern-C-non-FFI-safe-arg-ice-52334.rs:10:18 | LL | fn meh(blah: Foo); | ^^^ not FFI-safe | - = help: consider using a raw pointer instead - = note: slices have no C equivalent + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout = note: `#[warn(improper_ctypes)]` on by default warning: 2 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-const-arg-path.rs b/tests/ui/feature-gates/feature-gate-const-arg-path.rs new file mode 100644 index 00000000000..0938c5733a2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const-arg-path.rs @@ -0,0 +1,5 @@ +//@ check-pass + +// this doesn't really have any user facing impact.... + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.stderr b/tests/ui/feature-gates/feature-gate-repr-simd.stderr index 5b490c0c0c3..5a0ceb2dd74 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/tests/ui/feature-gates/feature-gate-repr-simd.stderr @@ -35,3 +35,17 @@ error: aborting due to 3 previous errors Some errors have detailed explanations: E0566, E0658. For more information about an error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +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 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.rs b/tests/ui/feature-gates/feature-gate-struct-target-features.rs new file mode 100644 index 00000000000..85494881146 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.rs @@ -0,0 +1,4 @@ +#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition +struct Avx {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr new file mode 100644 index 00000000000..1e18d3ee1e1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr @@ -0,0 +1,10 @@ +error: attribute should be applied to a function definition + --> $DIR/feature-gate-struct-target-features.rs:1:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | struct Avx {} + | ------------- not a function definition + +error: aborting due to 1 previous error + 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 index d1decc0c3f1..37491ca12b0 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -51,7 +51,7 @@ LL | type A<'a> where Self: 'a; = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: Fooy Fooer<T> - = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A = &'a ()> + 'static)>` + = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr index bb14e297174..88c08051da7 100644 --- a/tests/ui/generic-associated-types/issue-76535.base.stderr +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -47,7 +47,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = help: consider moving `SubType` to another trait = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type - = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType = SubStruct<'_>>>` + = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr index bcc6382cf7c..551ad2a8fdf 100644 --- a/tests/ui/generic-associated-types/issue-79422.base.stderr +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -49,7 +49,7 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: std::collections::BTreeMap<K, V> Source - = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>` + = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr index ae1526296a7..031f8d8d851 100644 --- a/tests/ui/generic-associated-types/issue-79422.extended.stderr +++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr @@ -28,7 +28,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a; = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` found reference `&u8` = help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box<dyn RefCont>`, you will have to change the expected type as well - = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>` + = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs index 9c067cb6934..2fde0f200c0 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -6,13 +6,13 @@ trait Bar<'a> { } fn foo<'a, T: Bar<'a>>() -> impl Into<T::Assoc> { - //~^ ERROR [o, o] + //~^ ERROR ['a: o, T: o] // captures both T and 'a invariantly () } fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + 'a { - //~^ ERROR [o, o, o] + //~^ ERROR ['a: o, T: o, 'a: o] // captures both T and 'a invariantly, and also duplicates `'a` // i.e. the opaque looks like `impl Into<<T as Bar<'a>>::Assoc> + 'a_duplicated` () diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr index 9d52001b024..fe8a2772a00 100644 --- a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -1,10 +1,10 @@ -error: [o, o] +error: ['a: o, T: o] --> $DIR/capture-lifetime-not-in-hir.rs:8:29 | LL | fn foo<'a, T: Bar<'a>>() -> impl Into<T::Assoc> { | ^^^^^^^^^^^^^^^^^^^ -error: [o, o, o] +error: ['a: o, T: o, 'a: o] --> $DIR/capture-lifetime-not-in-hir.rs:14:30 | LL | fn foo2<'a, T: Bar<'a>>() -> impl Into<T::Assoc> + 'a { diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr index 080750f8497..3adf78322d2 100644 --- a/tests/ui/impl-trait/implicit-capture-late.stderr +++ b/tests/ui/impl-trait/implicit-capture-late.stderr @@ -10,7 +10,7 @@ note: lifetime declared here LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> { | ^^ -error: [o] +error: ['a: o] --> $DIR/implicit-capture-late.rs:10:55 | LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> { diff --git a/tests/ui/impl-trait/in-trait/refine-err.rs b/tests/ui/impl-trait/in-trait/refine-err.rs new file mode 100644 index 00000000000..7518cee97c4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-err.rs @@ -0,0 +1,14 @@ +#![deny(refining_impl_trait)] + +trait FromRow { + fn prepare(self) -> impl Fn() -> T; + //~^ ERROR cannot find type `T` in this scope +} + +impl<T> FromRow for T { + fn prepare(self) -> impl Fn() -> T { + || todo!() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-err.stderr b/tests/ui/impl-trait/in-trait/refine-err.stderr new file mode 100644 index 00000000000..6b4ef74d50a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-err.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/refine-err.rs:4:38 + | +LL | fn prepare(self) -> impl Fn() -> T; + | ^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs index 7a51037324f..ab21dae7dc5 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs @@ -14,7 +14,6 @@ impl<'a, I: 'a + Iterable> Iterable for &'a I { //~^ ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR binding for associated type `Item` references lifetime `'missing` //~| ERROR `()` is not an iterator - //~| WARNING impl trait in impl method signature does not match trait method signature } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr index 67c4df0f3a9..d8a2eef94a1 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr @@ -32,24 +32,7 @@ LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missin | = help: the trait `Iterator` is not implemented for `()` -warning: impl trait in impl method signature does not match trait method signature - --> $DIR/span-bug-issue-121457.rs:13:51 - | -LL | fn iter(&self) -> impl Iterator; - | ------------- return type from trait method defined here -... -LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this bound is stronger than that defined on the trait - | - = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - = note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information - = note: `#[warn(refining_impl_trait_reachable)]` on by default -help: replace the return type so that it matches the trait - | -LL | fn iter(&self) -> impl Iterator {} - | ~~~~~~~~~~~~~ - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors Some errors have detailed explanations: E0195, E0277, E0582. For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 65565dcc2a6..0ac44bf7546 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -7,14 +7,16 @@ impl<T> Captures<'_> for T {} trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [o, *, *, o, o] - // Self, 'i, 'a, 'i_duplicated, 'a_duplicated + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [o, *, *, o, o] + fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} //~ [o, *, o, o] + fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o, *, o, o] + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} + //~^ [Self: o, 'i: *, 'a: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 8cae5a92f0d..54e0afbaa95 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,23 +1,23 @@ -error: [o, *, *, o, o] +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:9:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, *, o, o] - --> $DIR/variance.rs:13:44 +error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:12:44 | LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, *, o, o] +error: [Self: o, 'i: *, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o, *, o, o] - --> $DIR/variance.rs:17:48 +error: [Self: o, 'i: *, 'a: o, 'i: o] + --> $DIR/variance.rs:18:48 | LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed index 6bca8ef12ec..89a3f3136c8 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed @@ -5,14 +5,17 @@ fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 fn implicit(x: &i32) -> impl Sized + use<> { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 struct W; impl W { fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 + //~| WARN this changes meaning in Rust 2024 } trait Higher<'a> { @@ -24,5 +27,6 @@ impl Higher<'_> for () { fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized + use<>> {} //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs index 5b6726b49e0..18c04f9f799 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs @@ -5,14 +5,17 @@ fn named<'a>(x: &'a i32) -> impl Sized { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 fn implicit(x: &i32) -> impl Sized { *x } //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 struct W; impl W { fn hello(&self, x: &i32) -> impl Sized + '_ { self } //~^ ERROR `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 + //~| WARN this changes meaning in Rust 2024 } trait Higher<'a> { @@ -24,5 +27,6 @@ impl Higher<'_> for () { fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr index fec640aa83a..94dafb04d64 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr @@ -4,6 +4,8 @@ error: `impl Sized` will capture more lifetimes than possibly intended in editio LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } | ^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html> note: specifically, this lifetime is in scope but not mentioned in the type's bounds --> $DIR/overcaptures-2024.rs:6:10 | @@ -21,13 +23,15 @@ LL | fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } | +++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:9:25 + --> $DIR/overcaptures-2024.rs:10:25 | LL | fn implicit(x: &i32) -> impl Sized { *x } | ^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html> note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:9:16 + --> $DIR/overcaptures-2024.rs:10:16 | LL | fn implicit(x: &i32) -> impl Sized { *x } | ^ @@ -38,13 +42,15 @@ LL | fn implicit(x: &i32) -> impl Sized + use<> { *x } | +++++++ error: `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:14:33 + --> $DIR/overcaptures-2024.rs:16:33 | LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } | ^^^^^^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html> note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:14:24 + --> $DIR/overcaptures-2024.rs:16:24 | LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } | ^ @@ -55,13 +61,15 @@ LL | fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } | +++++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:25:47 + --> $DIR/overcaptures-2024.rs:28:47 | LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} | ^^^^^^^^^^ | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html> note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:25:23 + --> $DIR/overcaptures-2024.rs:28:23 | LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} | ^^ diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr index 17245055744..011ab3259c4 100644 --- a/tests/ui/impl-trait/variance.e2024.stderr +++ b/tests/ui/impl-trait/variance.e2024.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr index 17245055744..011ab3259c4 100644 --- a/tests/ui/impl-trait/variance.new.stderr +++ b/tests/ui/impl-trait/variance.new.stderr @@ -1,22 +1,22 @@ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:21:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr index 9410b54b491..ac3bcd2723f 100644 --- a/tests/ui/impl-trait/variance.old.stderr +++ b/tests/ui/impl-trait/variance.old.stderr @@ -1,10 +1,10 @@ -error: [*] +error: ['a: *] --> $DIR/variance.rs:14:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:19:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} @@ -16,7 +16,7 @@ error: [] LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [o] +error: ['a: o] --> $DIR/variance.rs:26:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index 72b4a831bad..43f7207a904 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -12,17 +12,17 @@ trait Captures<'a> {} impl<T> Captures<'_> for T {} fn not_captured_early<'a: 'a>() -> impl Sized {} -//[old]~^ [*] -//[new]~^^ [*, o] -//[e2024]~^^^ [*, o] +//[old]~^ ['a: *] +//[new]~^^ ['a: *, 'a: o] +//[e2024]~^^^ ['a: *, 'a: o] -fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [*, o] +fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ['a: *, 'a: o] fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} //[old]~^ [] -//[new]~^^ [o] -//[e2024]~^^^ [o] +//[new]~^^ ['a: o] +//[e2024]~^^^ ['a: o] -fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o] +fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ['a: o] fn main() {} diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index c8d1614a7f3..f498257e12f 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -5,9 +5,9 @@ LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'s` as defined here... - --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:12 + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:8:12 | -LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { +LL | fn get<'s>(s: &'s str, _: ()) -> &'static str; | ^^ note: ...so that the method type is compatible with trait --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:11:5 diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.rs b/tests/ui/inference/detect-old-time-version-format_description-parse.rs new file mode 100644 index 00000000000..453a795e768 --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.rs @@ -0,0 +1,8 @@ +#![crate_name = "time"] + +fn main() { + let items = Box::new(vec![]); //~ ERROR E0282 + //~^ NOTE type must be known at this point + //~| NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` + items.into(); +} diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr new file mode 100644 index 00000000000..2949a5dcfec --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `Box<Vec<_>>` + --> $DIR/detect-old-time-version-format_description-parse.rs:4:9 + | +LL | let items = Box::new(vec![]); + | ^^^^^ ---------------- type must be known at this point + | + = note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/internal/internal-unstable-const.rs b/tests/ui/internal/internal-unstable-const.rs deleted file mode 100644 index 4ec2426dfee..00000000000 --- a/tests/ui/internal/internal-unstable-const.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 deleted file mode 100644 index ed9196d2b63..00000000000 --- a/tests/ui/internal/internal-unstable-const.stderr +++ /dev/null @@ -1,19 +0,0 @@ -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 = "...")] -LL | pub const fn foo() -> f32 { - | -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)] -LL | pub const fn foo() -> f32 { - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index ab46fd796c5..99f98c3f27a 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -13,5 +13,13 @@ const RAW_EQ_PTR: bool = unsafe { //~| unable to turn pointer into integer }; +const RAW_EQ_NOT_ALIGNED: bool = unsafe { + let arr = [0u8; 4]; + let aref = &*arr.as_ptr().cast::<i32>(); + std::intrinsics::raw_eq(aref, aref) +//~^ ERROR evaluation of constant value failed +//~| alignment +}; + pub fn main() { } diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index af16c2bc64a..bedfc8283ea 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -13,6 +13,12 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = 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 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/intrinsic-raw_eq-const-bad.rs:19:5 + | +LL | std::intrinsics::raw_eq(aref, aref) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index 0119a1a6650..21b7bf4e1cb 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -7,9 +7,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | expected due to this | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::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; diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/issues/issue-17651.stderr index 0c95a3c0c40..9519507320d 100644 --- a/tests/ui/issues/issue-17651.stderr +++ b/tests/ui/issues/issue-17651.stderr @@ -9,6 +9,11 @@ LL | (|| Box::new(*(&[0][..])))(); = help: the trait `Sized` is not implemented for `[{integer}]` note: required by a bound in `Box::<T>::new` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - (|| Box::new(*(&[0][..])))(); +LL + (|| Box::new((&[0][..])))(); + | error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr index 60721f001b7..fe310998f09 100644 --- a/tests/ui/issues/issue-20831-debruijn.stderr +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -5,10 +5,10 @@ LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime as defined here... - --> $DIR/issue-20831-debruijn.rs:28:18 + --> $DIR/issue-20831-debruijn.rs:28:67 | LL | fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) { - | ^ + | ^^^^^^^^^ note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... --> $DIR/issue-20831-debruijn.rs:26:6 | diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr index b7c0095d682..17037d2180d 100644 --- a/tests/ui/issues/issue-37884.stderr +++ b/tests/ui/issues/issue-37884.stderr @@ -7,10 +7,7 @@ LL | fn next(&'a mut self) -> Option<Self::Item> = note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>` found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>` note: the anonymous lifetime as defined here... - --> $DIR/issue-37884.rs:6:5 - | -LL | fn next(&'a mut self) -> Option<Self::Item> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/issue-37884.rs:3:6 | diff --git a/tests/ui/issues/issue-47094.stderr b/tests/ui/issues/issue-47094.stderr index 970e3184710..1c6693403b8 100644 --- a/tests/ui/issues/issue-47094.stderr +++ b/tests/ui/issues/issue-47094.stderr @@ -23,3 +23,28 @@ LL | #[repr(u8)] error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0566`. +Future incompatibility report: Future breakage diagnostic: +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 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default + +Future breakage diagnostic: +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 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index bcacd01474f..8461d92fc33 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -2,12 +2,13 @@ struct ErrorKind; struct Error(ErrorKind); impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental [E0183] - //~^^ ERROR associated item constraints are not allowed here [E0229] + //~| ERROR associated item constraints are not allowed here [E0229] //~| ERROR not all trait items implemented //~| ERROR expected a `FnMut(&isize)` closure, found `Error` fn foo<const N: usize>(&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] + //~| ERROR method `foo` is not a member of trait `Fn` [E0407] + //~| ERROR associated type `B` not found for `Self` [E0220] + //~| ERROR: associated type `B` not found for `Self` } fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index cbc0eeebee1..310dee51406 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -56,7 +56,15 @@ error[E0220]: associated type `B` not found for `Self` LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>; | ^ help: `Self` has the following associated type: `Output` -error: aborting due to 7 previous errors +error[E0220]: associated type `B` not found for `Self` + --> $DIR/issue-95023.rs:8:44 + | +LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>; + | ^ help: `Self` has the following associated type: `Output` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/lint/dropping_copy_types-macros.fixed b/tests/ui/lint/dropping_copy_types-macros.fixed new file mode 100644 index 00000000000..a8ceedadc80 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.fixed @@ -0,0 +1,12 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +use std::fmt::Write; + +fn main() { + let mut msg = String::new(); + let _ = writeln!(&mut msg, "test"); + //~^ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.rs b/tests/ui/lint/dropping_copy_types-macros.rs new file mode 100644 index 00000000000..b249b0c868f --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.rs @@ -0,0 +1,12 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +use std::fmt::Write; + +fn main() { + let mut msg = String::new(); + drop(writeln!(&mut msg, "test")); + //~^ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.stderr b/tests/ui/lint/dropping_copy_types-macros.stderr new file mode 100644 index 00000000000..117e9f4fe09 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.stderr @@ -0,0 +1,21 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-macros.rs:10:5 + | +LL | drop(writeln!(&mut msg, "test")); + | ^^^^^--------------------------^ + | | + | argument has type `Result<(), std::fmt::Error>` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-macros.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(writeln!(&mut msg, "test")); +LL + let _ = writeln!(&mut msg, "test"); + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/lint-ctypes-cstr.rs b/tests/ui/lint/lint-ctypes-cstr.rs new file mode 100644 index 00000000000..b04decd0bca --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.rs @@ -0,0 +1,36 @@ +#![crate_type = "lib"] +#![deny(improper_ctypes, improper_ctypes_definitions)] + +use std::ffi::{CStr, CString}; + +extern "C" { + fn take_cstr(s: CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstr_ref(s: &CStr); + //~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring(s: CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + fn take_cstring_ref(s: &CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + + fn no_special_help_for_mut_cstring(s: *mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + + fn no_special_help_for_mut_cstring_ref(s: &mut CString); + //~^ ERROR `extern` block uses type `CString`, which is not FFI-safe + //~| HELP consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct +} + +extern "C" fn rust_take_cstr_ref(s: &CStr) {} +//~^ ERROR `extern` fn uses type `CStr`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_take_cstring(s: CString) {} +//~^ ERROR `extern` fn uses type `CString`, which is not FFI-safe +//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` +extern "C" fn rust_no_special_help_for_mut_cstring(s: *mut CString) {} +extern "C" fn rust_no_special_help_for_mut_cstring_ref(s: &mut CString) {} diff --git a/tests/ui/lint/lint-ctypes-cstr.stderr b/tests/ui/lint/lint-ctypes-cstr.stderr new file mode 100644 index 00000000000..8957758d577 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-cstr.stderr @@ -0,0 +1,84 @@ +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:7:21 + | +LL | fn take_cstr(s: CStr); + | ^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:9 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:10:25 + | +LL | fn take_cstr_ref(s: &CStr); + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:13:24 + | +LL | fn take_cstring(s: CString); + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:16:28 + | +LL | fn take_cstring_ref(s: &CString); + | ^^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: `extern` block uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:20:43 + | +LL | fn no_special_help_for_mut_cstring(s: *mut CString); + | ^^^^^^^^^^^^ 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 `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:24:47 + | +LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString); + | ^^^^^^^^^^^^ 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 `CStr`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:29:37 + | +LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {} + | ^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout +note: the lint level is defined here + --> $DIR/lint-ctypes-cstr.rs:2:26 + | +LL | #![deny(improper_ctypes, improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `CString`, which is not FFI-safe + --> $DIR/lint-ctypes-cstr.rs:32:36 + | +LL | extern "C" fn rust_take_cstring(s: CString) {} + | ^^^^^^^ not FFI-safe + | + = help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` + = note: `CStr`/`CString` do not have a guaranteed layout + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr index 09729eeba79..ef590d85aef 100644 --- a/tests/ui/lint/unused/lint-unused-variables.stderr +++ b/tests/ui/lint/unused/lint-unused-variables.stderr @@ -16,6 +16,12 @@ error: unused variable: `a` LL | a: i32, | ^ help: if this is intentional, prefix it with an underscore: `_a` +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:14:5 | @@ -58,12 +64,6 @@ error: unused variable: `b` 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 | diff --git a/tests/ui/methods/missing-method-on-type-parameter.rs b/tests/ui/methods/missing-method-on-type-parameter.rs new file mode 100644 index 00000000000..cbcbeea4d4c --- /dev/null +++ b/tests/ui/methods/missing-method-on-type-parameter.rs @@ -0,0 +1,6 @@ +// Regression test for https://github.com/rust-lang/rust/issues/129205 +fn x<T: Copy>() { + T::try_from(); //~ ERROR E0599 +} + +fn main() {} diff --git a/tests/ui/methods/missing-method-on-type-parameter.stderr b/tests/ui/methods/missing-method-on-type-parameter.stderr new file mode 100644 index 00000000000..c53d7afe4e2 --- /dev/null +++ b/tests/ui/methods/missing-method-on-type-parameter.stderr @@ -0,0 +1,19 @@ +error[E0599]: no function or associated item named `try_from` found for type parameter `T` in the current scope + --> $DIR/missing-method-on-type-parameter.rs:3:8 + | +LL | fn x<T: Copy>() { + | - function or associated item `try_from` not found for this type parameter +LL | T::try_from(); + | ^^^^^^^^ function or associated item not found in `T` + | + = help: items from traits can only be used if the trait is in scope +help: there is an associated function `from` with a similar name + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL +help: trait `TryFrom` which provides `try_from` is implemented but not in scope; perhaps you want to import it + | +LL + use std::convert::TryFrom; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index 1ba130e20b5..bd860841b80 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -359,11 +359,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } | 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:77:32 @@ -375,11 +370,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } | 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:79:32 @@ -391,11 +381,6 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | 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:85:35 diff --git a/tests/ui/parser/attribute/attr.stderr b/tests/ui/parser/attribute/attr.stderr index 2e0b16efb6c..a79a5246c2a 100644 --- a/tests/ui/parser/attribute/attr.stderr +++ b/tests/ui/parser/attribute/attr.stderr @@ -7,11 +7,6 @@ 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 1 previous error diff --git a/tests/ui/parser/inner-attr-after-doc-comment.stderr b/tests/ui/parser/inner-attr-after-doc-comment.stderr index 6dbc0fd93fd..f087c2e4d65 100644 --- a/tests/ui/parser/inner-attr-after-doc-comment.stderr +++ b/tests/ui/parser/inner-attr-after-doc-comment.stderr @@ -13,11 +13,6 @@ 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 1 previous error diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr index 57ca164fc15..18a82ea4c38 100644 --- a/tests/ui/parser/inner-attr.stderr +++ b/tests/ui/parser/inner-attr.stderr @@ -10,11 +10,6 @@ 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 1 previous error diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs new file mode 100644 index 00000000000..26541a89a56 --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] +fn foo() {} + +#![feature(iter_array_chunks)] //~ ERROR an inner attribute is not permitted in this context +fn bar() {} + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr new file mode 100644 index 00000000000..d6daa21e741 --- /dev/null +++ b/tests/ui/parser/issues/isgg-invalid-outer-attttr-issue-127930.stderr @@ -0,0 +1,12 @@ +error: an inner attribute is not permitted in this context + --> $DIR/isgg-invalid-outer-attttr-issue-127930.rs:4:1 + | +LL | #![feature(iter_array_chunks)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bar() {} + | ----------- 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 + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/issue-30318.fixed b/tests/ui/parser/issues/issue-30318.fixed index d1661be5193..d4720834746 100644 --- a/tests/ui/parser/issues/issue-30318.fixed +++ b/tests/ui/parser/issues/issue-30318.fixed @@ -6,7 +6,7 @@ fn foo() { } //~^ 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 +#[cfg(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 diff --git a/tests/ui/parser/issues/issue-30318.rs b/tests/ui/parser/issues/issue-30318.rs index 6f055cd4f7e..0555379836a 100644 --- a/tests/ui/parser/issues/issue-30318.rs +++ b/tests/ui/parser/issues/issue-30318.rs @@ -6,7 +6,7 @@ fn foo() { } //~^ 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 +#![cfg(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 diff --git a/tests/ui/parser/issues/issue-30318.stderr b/tests/ui/parser/issues/issue-30318.stderr index c441a92abad..56bc200db1d 100644 --- a/tests/ui/parser/issues/issue-30318.stderr +++ b/tests/ui/parser/issues/issue-30318.stderr @@ -15,16 +15,16 @@ LL | /// Misplaced comment... error: an inner attribute is not permitted in this context --> $DIR/issue-30318.rs:9:1 | -LL | #![test] - | ^^^^^^^^ +LL | #![cfg(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] +LL - #![cfg(test)] +LL + #[cfg(test)] | error[E0753]: expected outer doc comment diff --git a/tests/ui/regions/explicit-static-bound-on-trait.rs b/tests/ui/regions/explicit-static-bound-on-trait.rs new file mode 100644 index 00000000000..835da34d1bb --- /dev/null +++ b/tests/ui/regions/explicit-static-bound-on-trait.rs @@ -0,0 +1,13 @@ +struct Hello<'a> { + value: Box<dyn std::any::Any + 'a>, + //~^ ERROR lifetime bound not satisfied +} + +impl<'a> Hello<'a> { + fn new<T: 'a>(value: T) -> Self { + Self { value: Box::new(value) } + //~^ ERROR the parameter type `T` may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/regions/explicit-static-bound-on-trait.stderr b/tests/ui/regions/explicit-static-bound-on-trait.stderr new file mode 100644 index 00000000000..30d39c6e86e --- /dev/null +++ b/tests/ui/regions/explicit-static-bound-on-trait.stderr @@ -0,0 +1,32 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/explicit-static-bound-on-trait.rs:2:12 + | +LL | value: Box<dyn std::any::Any + 'a>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/explicit-static-bound-on-trait.rs:1:14 + | +LL | struct Hello<'a> { + | ^^ +note: but lifetime parameter must outlive the static lifetime + --> $SRC_DIR/core/src/any.rs:LL:COL + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/explicit-static-bound-on-trait.rs:8:23 + | +LL | Self { value: Box::new(value) } + | ^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn new<T: 'a + 'static>(value: T) -> Self { + | +++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0310, E0478. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/repr/conflicting-repr-hints.stderr b/tests/ui/repr/conflicting-repr-hints.stderr index 4dcd8f4fc28..fbfa69e7fb1 100644 --- a/tests/ui/repr/conflicting-repr-hints.stderr +++ b/tests/ui/repr/conflicting-repr-hints.stderr @@ -81,3 +81,25 @@ 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`. +Future incompatibility report: Future breakage diagnostic: +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 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default + +Future breakage diagnostic: +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 <https://github.com/rust-lang/rust/issues/68585> + = note: `#[deny(conflicting_repr_hints)]` on by default + diff --git a/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs new file mode 100644 index 00000000000..6ab34719f06 --- /dev/null +++ b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs @@ -0,0 +1,25 @@ +//@ check-pass + +#![feature(sync_unsafe_cell)] +#![allow(unused)] +#![deny(repr_transparent_external_private_fields)] + +// https://github.com/rust-lang/rust/issues/129470 + +struct ZST; + +#[repr(transparent)] +struct TransparentWithManuallyDropZST { + value: i32, + md: std::mem::ManuallyDrop<ZST>, + mu: std::mem::MaybeUninit<ZST>, + p: std::pin::Pin<ZST>, + pd: std::marker::PhantomData<ZST>, + pp: std::marker::PhantomPinned, + c: std::cell::Cell<ZST>, + uc: std::cell::UnsafeCell<ZST>, + suc: std::cell::SyncUnsafeCell<ZST>, + zst: ZST, +} + +fn main() {} diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed index a5a13399825..43a9907a9b4 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.fixed +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.fixed @@ -9,7 +9,6 @@ use std::io::prelude::*; fn test1() -> Result<(), Box<dyn std::error::Error>> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function - Ok(()) } @@ -17,7 +16,6 @@ fn test2() -> Result<(), Box<dyn std::error::Error>> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - Ok(()) } @@ -27,9 +25,8 @@ macro_rules! mac { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function println!(); - - Ok(()) -} + Ok(()) + } }; } @@ -39,23 +36,20 @@ impl A { fn test4(&self) -> Result<(), Box<dyn std::error::Error>> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a method - - Ok(()) -} + Ok(()) + } fn test5(&self) -> Result<(), Box<dyn std::error::Error>> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a method println!(); - - Ok(()) -} + Ok(()) + } } fn main() -> Result<(), Box<dyn std::error::Error>> { let mut _file = File::create("foo.txt")?; //~^ ERROR the `?` operator can only be used in a function mac!(); - Ok(()) } diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr index a59f38c2ec6..e22f33fd242 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr @@ -12,9 +12,7 @@ help: consider adding return type LL ~ fn test1() -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -32,9 +30,7 @@ LL ~ fn test2() -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -51,9 +47,8 @@ help: consider adding return type LL ~ fn test4(&self) -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -71,9 +66,8 @@ LL ~ fn test5(&self) -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -91,9 +85,7 @@ LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | LL | mac!(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) @@ -115,9 +107,8 @@ LL ~ fn test3() -> Result<(), Box<dyn std::error::Error>> { LL | let mut _file = File::create("foo.txt")?; LL | LL | println!(); -LL ~ -LL + Ok(()) -LL + } +LL ~ Ok(()) +LL ~ } | error: aborting due to 6 previous errors diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr index 16e1af46059..9b92166bcb7 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -16,6 +16,12 @@ error: unused variable: `a` LL | #[cfg(something)] a: i32, | ^ help: if this is intentional, prefix it with an underscore: `_a` +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:30:23 | @@ -100,12 +106,6 @@ error: unused variable: `c` 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 | diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs index 637a24f53bc..6c320c0462e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -1,4 +1,4 @@ -//@ check-pass +//~ ERROR the trait bound //@ compile-flags: -Znext-solver #![allow(incomplete_features)] @@ -17,6 +17,6 @@ impl Foo for S { } impl const Bar for S {} -//FIXME ~^ ERROR the trait bound +// FIXME(effects) bad span fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr new file mode 100644 index 00000000000..9a907bbee0a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Maybe: TyCompat<<(Foo::{synthetic#0},) as std::marker::effects::Intersection>::Output>` is not satisfied + | +note: required by a bound in `Bar::{synthetic#0}` + --> $DIR/super-traits-fail.rs:11:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 09926d95557..dc0d688284e 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -6,15 +6,20 @@ #![allow(incomplete_features)] #![feature(adt_const_params)] +use std::marker::ConstParamTy; + extern "rust-intrinsic" { fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U; } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)] #[repr(simd)] struct Simd<T, const N: usize>([T; N]); -pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U { +unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U { + simd_shuffle(x, y, IDX) +} +unsafe fn __shuffle_vector16_v2<const IDX: Simd<u32, 16>, T, U>(x: T, y: T) -> U { simd_shuffle(x, y, IDX) } @@ -30,6 +35,17 @@ fn main() { let y: Simd<u8, 2> = simd_shuffle(a, b, I2); assert_eq!(y.0, [1, 5]); } + // Test that we can also use a SIMD vector instead of a normal array for the shuffle. + const I1_SIMD: Simd<u32, 4> = Simd([0, 2, 4, 6]); + const I2_SIMD: Simd<u32, 2> = Simd([1, 5]); + unsafe { + let x: Simd<u8, 4> = simd_shuffle(a, b, I1_SIMD); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd<u8, 2> = simd_shuffle(a, b, I2_SIMD); + assert_eq!(y.0, [1, 5]); + } + // Test that an indirection (via an unnamed constant) // through a const generic parameter also works. // See https://github.com/rust-lang/rust/issues/113500 for details. @@ -42,4 +58,11 @@ fn main() { Simd<u8, 16>, >(a, b); } + unsafe { + __shuffle_vector16_v2::< + { Simd([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) }, + Simd<u8, 16>, + Simd<u8, 16>, + >(a, b); + } } diff --git a/tests/ui/sized/unsized-binding.stderr b/tests/ui/sized/unsized-binding.stderr index 7c3276032c2..8de236cd0b6 100644 --- a/tests/ui/sized/unsized-binding.stderr +++ b/tests/ui/sized/unsized-binding.stderr @@ -7,6 +7,11 @@ LL | let x = *""; = 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: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | error: aborting due to 1 previous error diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs new file mode 100644 index 00000000000..35abbb80d99 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs @@ -0,0 +1,30 @@ +fn foo() -> impl Sized { +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` + *"" //~ HELP consider not dereferencing the expression +} +fn bar(_: impl Sized) {} +struct S; + +impl S { + fn baz(&self, _: impl Sized) {} +} + +fn main() { + let _ = foo(); + let x = *""; + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + //~| HELP unsized locals are gated as an unstable feature + bar(x); + S.baz(x); + bar(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` + S.baz(*""); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| HELP consider not dereferencing the expression + //~| HELP the trait `Sized` is not implemented for `str` +} diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr new file mode 100644 index 00000000000..9b7258aff12 --- /dev/null +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr @@ -0,0 +1,74 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:1:13 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time +... +LL | *"" + | --- return type was inferred to be `str` here + | + = help: the trait `Sized` is not implemented for `str` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - *"" +LL + "" + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:15:9 + | +LL | let x = *""; + | ^ 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: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *""; +LL + let x = ""; + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:22:9 + | +LL | bar(*""); + | --- ^^^ 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 `bar` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:6:16 + | +LL | fn bar(_: impl Sized) {} + | ^^^^^ required by this bound in `bar` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - bar(*""); +LL + bar(""); + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:26:11 + | +LL | S.baz(*""); + | --- ^^^ 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 `S::baz` + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:10:27 + | +LL | fn baz(&self, _: impl Sized) {} + | ^^^^^ required by this bound in `S::baz` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - S.baz(*""); +LL + S.baz(""); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs index fb962ad24bf..858fba2132a 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs @@ -14,5 +14,6 @@ struct Wrapper<const C: <i32 as Trait>::Type> {} impl<const C: usize> Wrapper<C> {} //~^ ERROR the constant `C` is not of type `<i32 as Trait>::Type` +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr index 7094ee8c67c..71d4277275f 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -20,5 +20,17 @@ note: required by a const generic parameter in `Wrapper` LL | struct Wrapper<const C: <i32 as Trait>::Type> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30 + | +LL | impl<const C: usize> Wrapper<C> {} + | ^ expected associated type, found `usize` + | + = note: expected associated type `<i32 as Trait>::Type` + found type `usize` + = help: consider constraining the associated type `<i32 as Trait>::Type` to `usize` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index a0ee7714417..f89a463bc58 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -6,6 +6,7 @@ struct S<const L: usize>; impl<const N: i32> Copy for S<N> {} +//~^ ERROR: mismatched types impl<const M: usize> Copy for S<M> {} //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index 2953bc95917..1dac58e1f69 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -1,11 +1,19 @@ error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` - --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 + --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 | LL | impl<const N: i32> Copy for S<N> {} | -------------------------------- first implementation here +LL | LL | impl<const M: usize> Copy for S<M> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31 + | +LL | impl<const N: i32> Copy for S<N> {} + | ^ expected `usize`, found `i32` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index 4fd063e4692..c1ef1cd428e 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -66,6 +66,11 @@ note: required by a bound in `f_sized` | LL | fn f_sized<T: Sized>(t: T) {} | ^^^^^ required by this bound in `f_sized` +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - f_sized(*ref_cl); +LL + f_sized(ref_cl); + | error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/issue-84973-blacklist.rs:27:12 diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 94d79d56c59..5c4fb847932 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-ermsb_target_feature // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature +// gate-test-aarch64_unstable_target_feature // gate-test-csky_target_feature // gate-test-loongarch_target_feature // gate-test-lahfsahf_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index a69020e6864..37c5ed01688 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:26:18 + --> $DIR/gate.rs:27:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs new file mode 100644 index 00000000000..feb479b6dc8 --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.rs @@ -0,0 +1,98 @@ +//@ only-x86_64 +#![feature(struct_target_features)] +//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes +#![feature(target_feature_11)] + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +//~^ ERROR attribute should be applied to a function definition or unit struct +struct Invalid(u32); + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "sse")] +struct Sse(); + +#[target_feature(enable = "avx")] +fn avx() {} + +trait TFAssociatedType { + type Assoc; +} + +impl TFAssociatedType for () { + type Assoc = Avx; +} + +fn avx_self(_: <() as TFAssociatedType>::Assoc) { + avx(); +} + +fn avx_avx(_: Avx) { + avx(); +} + +extern "C" fn bad_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI + +#[inline(always)] +//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]` +fn inline_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a #[inline(always)] function + +trait Simd { + fn do_something(&self); +} + +impl Simd for Avx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +impl Simd for Sse { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm_setzero_ps()); + } + } +} + +struct WithAvx { + #[allow(dead_code)] + avx: Avx, +} + +impl Simd for WithAvx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +#[inline(never)] +fn dosomething<S: Simd>(simd: &S) { + simd.do_something(); +} + +fn avxfn(_: &Avx) {} + +fn main() { + Avx {}; + //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133] + + if is_x86_feature_detected!("avx") { + let avx = unsafe { Avx {} }; + avxfn(&avx); + dosomething(&avx); + dosomething(&WithAvx { avx }); + } + if is_x86_feature_detected!("sse") { + dosomething(&unsafe { Sse {} }) + } +} diff --git a/tests/ui/target-feature/struct-target-features.stderr b/tests/ui/target-feature/struct-target-features.stderr new file mode 100644 index 00000000000..5ef863f504e --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.stderr @@ -0,0 +1,47 @@ +warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/struct-target-features.rs:2:12 + | +LL | #![feature(struct_target_features)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: attribute should be applied to a function definition or unit struct + --> $DIR/struct-target-features.rs:8:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Invalid(u32); + | -------------------- not a function definition or a unit struct + +error: cannot use a struct with target features in a function with non-Rust ABI + --> $DIR/struct-target-features.rs:37:1 + | +LL | extern "C" fn bad_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a struct with target features in a #[inline(always)] function + --> $DIR/struct-target-features.rs:42:1 + | +LL | fn inline_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/struct-target-features.rs:40:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block + --> $DIR/struct-target-features.rs:86:5 + | +LL | Avx {}; + | ^^^^^^ initializing type with `target_feature` attr + | + = note: this struct can only be constructed if the corresponding `target_feature`s are available + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs index 8958871ed5d..6660ff040f7 100644 --- a/tests/ui/traits/object/pretty.rs +++ b/tests/ui/traits/object/pretty.rs @@ -18,6 +18,10 @@ trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {} trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {} +trait HasGat<Outer> { + type Assoc<Inner> where Self: Sized; +} + fn dyn_super(x: &dyn Super<Assoc = u8>) { x } //~ERROR mismatched types fn dyn_any(x: &dyn Any<Assoc = u8>) { x } //~ERROR mismatched types fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types @@ -34,4 +38,7 @@ fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types +fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x } //~ERROR mismatched types +//~^ WARN unnecessary associated type bound + fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index bc645e5f967..6964d97c08e 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -1,5 +1,14 @@ +warning: unnecessary associated type bound for not object safe associated type + --> $DIR/pretty.rs:41:35 + | +LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x } + | ^^^^^^^^^^^^^^^^ help: remove this bound + | + = note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` + = note: `#[warn(unused_associated_type_bounds)]` on by default + error[E0308]: mismatched types - --> $DIR/pretty.rs:21:43 + --> $DIR/pretty.rs:25:43 | LL | fn dyn_super(x: &dyn Super<Assoc = u8>) { x } | - ^ expected `()`, found `&dyn Super<Assoc = u8>` @@ -10,7 +19,7 @@ LL | fn dyn_super(x: &dyn Super<Assoc = u8>) { x } found reference `&dyn Super<Assoc = u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:22:39 + --> $DIR/pretty.rs:26:39 | LL | fn dyn_any(x: &dyn Any<Assoc = u8>) { x } | - ^ expected `()`, found `&dyn Any<Assoc = u8>` @@ -21,7 +30,7 @@ LL | fn dyn_any(x: &dyn Any<Assoc = u8>) { x } found reference `&dyn Any<Assoc = u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:23:31 + --> $DIR/pretty.rs:27:31 | LL | fn dyn_fixed(x: &dyn Fixed) { x } | - ^ expected `()`, found `&dyn Fixed` @@ -32,7 +41,7 @@ LL | fn dyn_fixed(x: &dyn Fixed) { x } found reference `&dyn Fixed` error[E0308]: mismatched types - --> $DIR/pretty.rs:24:50 + --> $DIR/pretty.rs:28:50 | LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x } | - ^ expected `()`, found `&dyn Fixed<Assoc = u16>` @@ -43,7 +52,7 @@ LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x } found reference `&dyn Fixed<Assoc = u16>` error[E0308]: mismatched types - --> $DIR/pretty.rs:25:38 + --> $DIR/pretty.rs:29:38 | LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } | - ^ expected `()`, found `&dyn FixedSub` @@ -54,7 +63,7 @@ LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } found reference `&dyn FixedSub` error[E0308]: mismatched types - --> $DIR/pretty.rs:26:44 + --> $DIR/pretty.rs:30:44 | LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } | - ^ expected `()`, found `&dyn FixedStatic` @@ -65,7 +74,7 @@ LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } found reference `&dyn FixedStatic` error[E0308]: mismatched types - --> $DIR/pretty.rs:28:75 + --> $DIR/pretty.rs:32:75 | LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` @@ -76,7 +85,7 @@ LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:29:71 + --> $DIR/pretty.rs:33:71 | LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` @@ -87,7 +96,7 @@ LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:30:60 + --> $DIR/pretty.rs:34:60 | LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` @@ -98,7 +107,7 @@ LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } found reference `&dyn for<'a> FixedGeneric1<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:31:60 + --> $DIR/pretty.rs:35:60 | LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` @@ -109,7 +118,7 @@ LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } found reference `&dyn for<'a> FixedGeneric2<'a>` error[E0308]: mismatched types - --> $DIR/pretty.rs:32:79 + --> $DIR/pretty.rs:36:79 | LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` @@ -120,7 +129,7 @@ LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:33:40 + --> $DIR/pretty.rs:37:40 | LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } | - ^ expected `()`, found `&dyn FixedHrtb` @@ -131,7 +140,7 @@ LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } found reference `&dyn FixedHrtb` error[E0308]: mismatched types - --> $DIR/pretty.rs:34:73 + --> $DIR/pretty.rs:38:73 | LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } | - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = ...>` @@ -142,7 +151,7 @@ LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } found reference `&dyn AnyDifferentBinders<Assoc = u8>` error[E0308]: mismatched types - --> $DIR/pretty.rs:35:65 + --> $DIR/pretty.rs:39:65 | LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } | - ^ expected `()`, found `&dyn FixedDifferentBinders` @@ -152,6 +161,17 @@ LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } = note: expected unit type `()` found reference `&dyn FixedDifferentBinders` -error: aborting due to 14 previous errors +error[E0308]: mismatched types + --> $DIR/pretty.rs:41:56 + | +LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x } + | - ^ expected `()`, found `&dyn HasGat<u8, Assoc<bool> = ()>` + | | + | help: try adding a return type: `-> &dyn HasGat<u8, Assoc<bool> = ()>` + | + = note: expected unit type `()` + found reference `&dyn HasGat<u8, Assoc<bool> = ()>` + +error: aborting due to 15 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/abstraction/abstracted_assume.rs b/tests/ui/transmutability/abstraction/abstracted_assume.rs index 897e1b4b50a..7fd91e31a04 100644 --- a/tests/ui/transmutability/abstraction/abstracted_assume.rs +++ b/tests/ui/transmutability/abstraction/abstracted_assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -16,7 +16,7 @@ mod assert { const ASSUME: std::mem::Assume, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, ASSUME, >, diff --git a/tests/ui/transmutability/abstraction/const_generic_fn.rs b/tests/ui/transmutability/abstraction/const_generic_fn.rs index 0a5f0de0214..1ea978ce1ba 100644 --- a/tests/ui/transmutability/abstraction/const_generic_fn.rs +++ b/tests/ui/transmutability/abstraction/const_generic_fn.rs @@ -6,12 +6,12 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn array_like<T, E, const N: usize>() where - T: BikeshedIntrinsicFrom<[E; N], { Assume::SAFETY }>, - [E; N]: BikeshedIntrinsicFrom<T, { Assume::SAFETY }> + T: TransmuteFrom<[E; N], { Assume::SAFETY }>, + [E; N]: TransmuteFrom<T, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/alignment/align-fail.rs b/tests/ui/transmutability/alignment/align-fail.rs index d88f1285c11..4c1a69b0128 100644 --- a/tests/ui/transmutability/alignment/align-fail.rs +++ b/tests/ui/transmutability/alignment/align-fail.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: true, diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index f05e55fb024..b9801e511b2 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: false, diff --git a/tests/ui/transmutability/alignment/align-pass.rs b/tests/ui/transmutability/alignment/align-pass.rs index aecf7b02d62..feecf5edaa1 100644 --- a/tests/ui/transmutability/alignment/align-pass.rs +++ b/tests/ui/transmutability/alignment/align-pass.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, diff --git a/tests/ui/transmutability/arrays/huge-len.rs b/tests/ui/transmutability/arrays/huge-len.rs index 3fe254ebef4..dec24a559d3 100644 --- a/tests/ui/transmutability/arrays/huge-len.rs +++ b/tests/ui/transmutability/arrays/huge-len.rs @@ -1,11 +1,11 @@ #![crate_type = "lib"] #![feature(transmutability)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr index 3fc652f47c1..1fa16c649d4 100644 --- a/tests/ui/transmutability/arrays/huge-len.stderr +++ b/tests/ui/transmutability/arrays/huge-len.stderr @@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `ExplicitlyPadded` --> $DIR/huge-len.rs:21:41 | LL | assert::is_maybe_transmutable::<(), ExplicitlyPadded>(); - | ^^^^^^^^^^^^^^^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported + | ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the current architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 @@ -10,14 +10,14 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src>, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` --> $DIR/huge-len.rs:24:55 | LL | assert::is_maybe_transmutable::<ExplicitlyPadded, ()>(); - | ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported + | ^^ values of the type `ExplicitlyPadded` are too big for the current architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src>, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.rs b/tests/ui/transmutability/arrays/issue-103783-array-length.rs index 7fcbcc01075..3537a39259c 100644 --- a/tests/ui/transmutability/arrays/issue-103783-array-length.rs +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.rs @@ -3,11 +3,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/arrays/should_have_correct_length.rs b/tests/ui/transmutability/arrays/should_have_correct_length.rs index 747897d49d7..00c0c1122ef 100644 --- a/tests/ui/transmutability/arrays/should_have_correct_length.rs +++ b/tests/ui/transmutability/arrays/should_have_correct_length.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/arrays/should_inherit_alignment.rs b/tests/ui/transmutability/arrays/should_inherit_alignment.rs index d95c51e3361..70d2f07c449 100644 --- a/tests/ui/transmutability/arrays/should_inherit_alignment.rs +++ b/tests/ui/transmutability/arrays/should_inherit_alignment.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs index 5345b199f6e..29e8ad136ee 100644 --- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr index b4cd70142c4..e9420cd393e 100644 --- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -31,7 +31,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -52,7 +52,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -73,7 +73,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -94,7 +94,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -115,7 +115,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/niche_optimization.rs b/tests/ui/transmutability/enums/niche_optimization.rs index 23f57ecad75..802d1747568 100644 --- a/tests/ui/transmutability/enums/niche_optimization.rs +++ b/tests/ui/transmutability/enums/niche_optimization.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, @@ -21,7 +21,7 @@ mod assert { pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, diff --git a/tests/ui/transmutability/enums/repr/padding_differences.rs b/tests/ui/transmutability/enums/repr/padding_differences.rs index d0e1502b5e2..9d2380c613e 100644 --- a/tests/ui/transmutability/enums/repr/padding_differences.rs +++ b/tests/ui/transmutability/enums/repr/padding_differences.rs @@ -7,11 +7,11 @@ use std::mem::MaybeUninit; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, @@ -23,7 +23,7 @@ mod assert { pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, 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 index d3d463e7929..a8f4cccc73e 100644 --- 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 @@ -5,11 +5,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, 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 index 6c88bf4ff96..c975ff276c8 100644 --- 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 @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -32,7 +32,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -54,7 +54,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -76,7 +76,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -98,7 +98,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -120,7 +120,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -142,7 +142,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -164,7 +164,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -186,7 +186,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -208,7 +208,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -230,7 +230,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -252,7 +252,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -274,7 +274,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -296,7 +296,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -318,7 +318,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -340,7 +340,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -362,7 +362,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -384,7 +384,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -406,7 +406,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -428,7 +428,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/enums/repr/should_handle_all.rs b/tests/ui/transmutability/enums/repr/should_handle_all.rs index a8ec86fa40d..dec0126f22d 100644 --- a/tests/ui/transmutability/enums/repr/should_handle_all.rs +++ b/tests/ui/transmutability/enums/repr/should_handle_all.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/enums/should_order_correctly.rs b/tests/ui/transmutability/enums/should_order_correctly.rs index d51a033f1a6..cea2055e148 100644 --- a/tests/ui/transmutability/enums/should_order_correctly.rs +++ b/tests/ui/transmutability/enums/should_order_correctly.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_pad_variants.rs b/tests/ui/transmutability/enums/should_pad_variants.rs index 81ef9e8a567..82bafe85415 100644 --- a/tests/ui/transmutability/enums/should_pad_variants.rs +++ b/tests/ui/transmutability/enums/should_pad_variants.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr index da4294bdbce..bb26281c2f0 100644 --- a/tests/ui/transmutability/enums/should_pad_variants.stderr +++ b/tests/ui/transmutability/enums/should_pad_variants.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/should_respect_endianness.rs b/tests/ui/transmutability/enums/should_respect_endianness.rs index 8e52274710a..9cf4de06ad2 100644 --- a/tests/ui/transmutability/enums/should_respect_endianness.rs +++ b/tests/ui/transmutability/enums/should_respect_endianness.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr index 9f88bb06813..1b9099b297b 100644 --- a/tests/ui/transmutability/enums/should_respect_endianness.stderr +++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/uninhabited_optimization.rs b/tests/ui/transmutability/enums/uninhabited_optimization.rs index c2d5b67ab2c..5b9de3a3963 100644 --- a/tests/ui/transmutability/enums/uninhabited_optimization.rs +++ b/tests/ui/transmutability/enums/uninhabited_optimization.rs @@ -4,7 +4,7 @@ fn assert_transmutable<T>() where - (): std::mem::BikeshedIntrinsicFrom<T> + (): std::mem::TransmuteFrom<T> {} enum Uninhabited {} diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index 20bd7917e53..fcc1db073ee 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -1,12 +1,13 @@ #![feature(transmutability)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, const ASSUME_ALIGNMENT: bool>() where - Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope - //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume` + Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope + //~| the constant `ASSUME_ALIGNMENT` is not of type `Assume` + //~| ERROR: mismatched types { } } diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index ba18a980f4d..3687631dc51 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -1,18 +1,25 @@ error[E0412]: cannot find type `Dst` in this scope --> $DIR/issue-101739-1.rs:8:9 | -LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, | ^^^ not found in this scope error: the constant `ASSUME_ALIGNMENT` is not of type `Assume` --> $DIR/issue-101739-1.rs:8:14 | -LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` | -note: required by a const generic parameter in `BikeshedIntrinsicFrom` +note: required by a const generic parameter in `TransmuteFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-101739-1.rs:8:33 + | +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, + | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0412`. +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 index 8b36bf3dcb1..02aa4669e05 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -14,19 +14,23 @@ mod assert { const ASSUME_VISIBILITY: bool, >() where - Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied - Src, - ASSUME_ALIGNMENT, - ASSUME_LIFETIMES, - ASSUME_VALIDITY, - ASSUME_VISIBILITY, - >, - {} + Dst: TransmuteFrom< + //~^ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied + Src, + ASSUME_ALIGNMENT, //~ ERROR: mismatched types + ASSUME_LIFETIMES, + ASSUME_VALIDITY, + ASSUME_VISIBILITY, + >, + { + } } fn via_const() { - #[repr(C)] struct Src; - #[repr(C)] struct Dst; + #[repr(C)] + struct Src; + #[repr(C)] + struct Dst; const FALSE: bool = false; diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 6b0a36a414b..526fcabe14e 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -1,16 +1,23 @@ error[E0107]: trait takes at most 2 generic arguments but 5 generic arguments were supplied --> $DIR/issue-101739-2.rs:17:14 | -LL | Dst: BikeshedIntrinsicFrom< - | ^^^^^^^^^^^^^^^^^^^^^ expected at most 2 generic arguments -LL | Src, -LL | ASSUME_ALIGNMENT, - | _____________________________- -LL | | ASSUME_LIFETIMES, -LL | | ASSUME_VALIDITY, -LL | | ASSUME_VISIBILITY, - | |_____________________________- help: remove the unnecessary generic arguments +LL | Dst: TransmuteFrom< + | ^^^^^^^^^^^^^ expected at most 2 generic arguments +... +LL | ASSUME_ALIGNMENT, + | _________________________________- +LL | | ASSUME_LIFETIMES, +LL | | ASSUME_VALIDITY, +LL | | ASSUME_VISIBILITY, + | |_________________________________- help: remove the unnecessary generic arguments -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/issue-101739-2.rs:20:17 + | +LL | ASSUME_ALIGNMENT, + | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/issue-110467.rs b/tests/ui/transmutability/issue-110467.rs index 1f9e521c24b..4acea5f766d 100644 --- a/tests/ui/transmutability/issue-110467.rs +++ b/tests/ui/transmutability/issue-110467.rs @@ -1,11 +1,11 @@ //@ check-pass #![crate_type = "lib"] #![feature(transmutability)] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } diff --git a/tests/ui/transmutability/issue-110892.rs b/tests/ui/transmutability/issue-110892.rs index 9713684c959..ad1b9e7af10 100644 --- a/tests/ui/transmutability/issue-110892.rs +++ b/tests/ui/transmutability/issue-110892.rs @@ -3,7 +3,7 @@ #![allow(incomplete_features)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -14,7 +14,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs index 30c381745d0..07133aa5614 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; //~^ ERROR use of unstable library feature 'transmutability' [E0658] use std::mem::Assume; diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr index 9f221907172..a2096cd53e5 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature 'transmutability' --> $DIR/feature-missing.rs:5:5 | -LL | use std::mem::BikeshedIntrinsicFrom; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use std::mem::TransmuteFrom; + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information = help: add `#![feature(transmutability)]` to the crate attributes to enable diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs index bcfbc1430a8..b8828c59d35 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs new file mode 100644 index 00000000000..2285d2f532e --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs @@ -0,0 +1,26 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::TransmuteFrom; + + pub fn is_transmutable<Src, Dst>() + where + Dst: TransmuteFrom<Src> + {} +} + +fn should_gracefully_handle_unknown_dst_field() { + #[repr(C)] struct Src; + #[repr(C)] struct Dst(Missing); //~ cannot find type + assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted +} + +fn should_gracefully_handle_unknown_dst_ref_field() { + #[repr(C)] struct Src(&'static Src); + #[repr(C)] struct Dst(&'static Missing); //~ cannot find type + assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr new file mode 100644 index 00000000000..564aee687a5 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr @@ -0,0 +1,46 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_dst_field.rs:18:27 + | +LL | #[repr(C)] struct Dst(Missing); + | ^^^^^^^ not found in this scope + +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_dst_field.rs:24:36 + | +LL | #[repr(C)] struct Dst(&'static Missing); + | ^^^^^^^ not found in this scope + +error[E0277]: `should_gracefully_handle_unknown_dst_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_field::Dst` + --> $DIR/unknown_dst_field.rs:19:36 + | +LL | assert::is_transmutable::<Src, Dst>(); + | ^^^ `should_gracefully_handle_unknown_dst_field::Dst` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_dst_field.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `should_gracefully_handle_unknown_dst_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_ref_field::Dst` + --> $DIR/unknown_dst_field.rs:25:36 + | +LL | assert::is_transmutable::<Src, Dst>(); + | ^^^ `should_gracefully_handle_unknown_dst_ref_field::Dst` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_dst_field.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +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/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs index bd7c3fc7fb5..10ba7a61b87 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs index 58c16d773e1..598e04971e2 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -5,16 +5,22 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } -fn should_gracefully_handle_unknown_dst_field() { - #[repr(C)] struct Src; - #[repr(C)] struct Dst(Missing); //~ cannot find type +fn should_gracefully_handle_unknown_src_field() { + #[repr(C)] struct Src(Missing); //~ cannot find type + #[repr(C)] struct Dst(); + assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted +} + +fn should_gracefully_handle_unknown_src_ref_field() { + #[repr(C)] struct Src(&'static Missing); //~ cannot find type + #[repr(C)] struct Dst(&'static Dst); assert::is_transmutable::<Src, Dst>(); //~ ERROR cannot be safely transmuted } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr index cabc7bcfef7..1156391c301 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -1,14 +1,35 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/unknown_src_field.rs:18:27 + --> $DIR/unknown_src_field.rs:17:27 | -LL | #[repr(C)] struct Dst(Missing); +LL | #[repr(C)] struct Src(Missing); | ^^^^^^^ not found in this scope -error[E0277]: `Src` cannot be safely transmuted into `Dst` +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_src_field.rs:23:36 + | +LL | #[repr(C)] struct Src(&'static Missing); + | ^^^^^^^ not found in this scope + +error[E0277]: `should_gracefully_handle_unknown_src_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_field::Dst` --> $DIR/unknown_src_field.rs:19:36 | LL | assert::is_transmutable::<Src, Dst>(); - | ^^^ analyzing the transmutability of `Dst` is not yet supported + | ^^^ `should_gracefully_handle_unknown_src_field::Src` has an unknown layout + | +note: required by a bound in `is_transmutable` + --> $DIR/unknown_src_field.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `should_gracefully_handle_unknown_src_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_ref_field::Dst` + --> $DIR/unknown_src_field.rs:25:36 + | +LL | assert::is_transmutable::<Src, Dst>(); + | ^^^ `should_gracefully_handle_unknown_src_ref_field::Src` has an unknown layout | note: required by a bound in `is_transmutable` --> $DIR/unknown_src_field.rs:12:14 @@ -16,10 +37,10 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` -error: aborting due to 2 previous errors +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/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs index 608366fa089..df925975bad 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -19,7 +19,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/maybeuninit.rs b/tests/ui/transmutability/maybeuninit.rs index 77c3381c774..7b60785b7e0 100644 --- a/tests/ui/transmutability/maybeuninit.rs +++ b/tests/ui/transmutability/maybeuninit.rs @@ -5,11 +5,11 @@ use std::mem::MaybeUninit; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/maybeuninit.stderr b/tests/ui/transmutability/maybeuninit.stderr index be7dcaf35ea..897c2df10a8 100644 --- a/tests/ui/transmutability/maybeuninit.stderr +++ b/tests/ui/transmutability/maybeuninit.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool-mut.rs b/tests/ui/transmutability/primitives/bool-mut.rs index 09b6d582d87..0a7dad37aaf 100644 --- a/tests/ui/transmutability/primitives/bool-mut.rs +++ b/tests/ui/transmutability/primitives/bool-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr index a6cf146659e..fcf60bc979c 100644 --- a/tests/ui/transmutability/primitives/bool-mut.stderr +++ b/tests/ui/transmutability/primitives/bool-mut.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.current.stderr +++ b/tests/ui/transmutability/primitives/bool.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.next.stderr +++ b/tests/ui/transmutability/primitives/bool.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs index 19236a1ae2e..6fac8ba1ad1 100644 --- a/tests/ui/transmutability/primitives/bool.rs +++ b/tests/ui/transmutability/primitives/bool.rs @@ -4,16 +4,16 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs index 401502474cf..b5c21c992b6 100644 --- a/tests/ui/transmutability/primitives/numbers.rs +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -7,11 +7,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr index 52b708d680e..4bfb229832b 100644 --- a/tests/ui/transmutability/primitives/unit.current.stderr +++ b/tests/ui/transmutability/primitives/unit.current.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/primitives/unit.next.stderr b/tests/ui/transmutability/primitives/unit.next.stderr index 52b708d680e..4bfb229832b 100644 --- a/tests/ui/transmutability/primitives/unit.next.stderr +++ b/tests/ui/transmutability/primitives/unit.next.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs index 44216950f55..93b21e0b586 100644 --- a/tests/ui/transmutability/primitives/unit.rs +++ b/tests/ui/transmutability/primitives/unit.rs @@ -9,11 +9,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs b/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs index 3bdd7256791..edad02fc96d 100644 --- a/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs +++ b/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::LIFETIMES) }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::LIFETIMES) }>, { core::intrinsics::transmute_unchecked(src) } @@ -82,7 +82,7 @@ mod hrtb { unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 where - for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8, { Assume::LIFETIMES }>, + for<'b> &'b u8: TransmuteFrom<&'a u8, { Assume::LIFETIMES }>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs index 559ee23a446..5734575e90b 100644 --- a/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs +++ b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY }>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs index ba2db755e3b..92068ee0d4f 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr index 4b2866dc4f0..1698021d554 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs index cd70c278285..8e2da3518a9 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs index 2f264e8339e..01b176cc3c1 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr index 2b7cab1660d..dbd3e39b365 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.rs b/tests/ui/transmutability/references/recursive-wrapper-types.rs index 28f4d6661cb..53dedeb6388 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/reject_extension.rs b/tests/ui/transmutability/references/reject_extension.rs index 161da5772e8..dd02e5c01c4 100644 --- a/tests/ui/transmutability/references/reject_extension.rs +++ b/tests/ui/transmutability/references/reject_extension.rs @@ -6,11 +6,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { diff --git a/tests/ui/transmutability/references/reject_extension.stderr b/tests/ui/transmutability/references/reject_extension.stderr index 88dd0313e3c..182106acf12 100644 --- a/tests/ui/transmutability/references/reject_extension.stderr +++ b/tests/ui/transmutability/references/reject_extension.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom< +LL | Dst: TransmuteFrom< | ______________^ LL | | Src, LL | | { diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.rs b/tests/ui/transmutability/references/reject_lifetime_extension.rs index 79bb4e1e556..ff9290c34af 100644 --- a/tests/ui/transmutability/references/reject_lifetime_extension.rs +++ b/tests/ui/transmutability/references/reject_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY }>, { core::intrinsics::transmute_unchecked(src) } @@ -82,7 +82,7 @@ mod hrtb { unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 where - for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8>, + for<'b> &'b u8: TransmuteFrom<&'a u8>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.stderr b/tests/ui/transmutability/references/reject_lifetime_extension.stderr index df1b81f26d2..a597041c6ca 100644 --- a/tests/ui/transmutability/references/reject_lifetime_extension.stderr +++ b/tests/ui/transmutability/references/reject_lifetime_extension.stderr @@ -70,8 +70,8 @@ LL | unsafe { extend_hrtb(src) } note: due to current limitations in the borrow checker, this implies a `'static` lifetime --> $DIR/reject_lifetime_extension.rs:85:25 | -LL | for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | for<'b> &'b u8: TransmuteFrom<&'a u8>, + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/transmutability/references/u8-to-unit.rs b/tests/ui/transmutability/references/u8-to-unit.rs index 017b73d9595..98deb6457cb 100644 --- a/tests/ui/transmutability/references/u8-to-unit.rs +++ b/tests/ui/transmutability/references/u8-to-unit.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: true, diff --git a/tests/ui/transmutability/references/unit-to-itself.rs b/tests/ui/transmutability/references/unit-to-itself.rs index 40aec8418fe..789455c03ea 100644 --- a/tests/ui/transmutability/references/unit-to-itself.rs +++ b/tests/ui/transmutability/references/unit-to-itself.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/unit-to-u8.rs b/tests/ui/transmutability/references/unit-to-u8.rs index 973d3206c12..575a40e3622 100644 --- a/tests/ui/transmutability/references/unit-to-u8.rs +++ b/tests/ui/transmutability/references/unit-to-u8.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index 5d73dfdc8eb..b5a79b1917f 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/unsafecell.rs b/tests/ui/transmutability/references/unsafecell.rs index a8a1f969fb4..4001f139770 100644 --- a/tests/ui/transmutability/references/unsafecell.rs +++ b/tests/ui/transmutability/references/unsafecell.rs @@ -5,11 +5,11 @@ use std::cell::UnsafeCell; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr index 8bb32359355..6664d8a7d6f 100644 --- a/tests/ui/transmutability/references/unsafecell.stderr +++ b/tests/ui/transmutability/references/unsafecell.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8>` --> $DIR/unsafecell.rs:29:62 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/region-infer.rs b/tests/ui/transmutability/region-infer.rs index 0632bc53176..c164f35c447 100644 --- a/tests/ui/transmutability/region-infer.rs +++ b/tests/ui/transmutability/region-infer.rs @@ -1,13 +1,13 @@ #![feature(transmutability)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; #[repr(C)] struct W<'a>(&'a ()); fn test<'a>() where - W<'a>: BikeshedIntrinsicFrom< + W<'a>: TransmuteFrom< (), { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 03c46823838..09ecf484bc8 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -10,7 +10,7 @@ note: required by a bound in `test` LL | fn test<'a>() | ---- required by a bound in this function LL | where -LL | W<'a>: BikeshedIntrinsicFrom< +LL | W<'a>: TransmuteFrom< | ____________^ LL | | (), LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs index cb3c1cdf46c..0113049f51e 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs index b12c4a10d12..eca7a06559d 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs index ff01462ffec..46e84b48044 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs index d516e9a7da5..aaba6febde4 100644 --- a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs index 4f0aee31548..6f8e383db1f 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr index 2339c268326..6445b1e146e 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs index 126059dd7b7..16d163d5420 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr index 99feebe9211..38ef829f064 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/structs/repr/should_handle_align.rs b/tests/ui/transmutability/structs/repr/should_handle_align.rs index 0c207766045..03065298b50 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_align.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/should_handle_all.rs b/tests/ui/transmutability/structs/repr/should_handle_all.rs index 52c24eecf12..e5ca37e68ec 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_all.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_all.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/should_handle_packed.rs b/tests/ui/transmutability/structs/repr/should_handle_packed.rs index 4af32d6e84e..c9be32d7b2a 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_packed.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_packed.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs index 64110753832..8d291054365 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs @@ -7,11 +7,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } @@ -22,5 +22,4 @@ fn should_pad_explicitly_packed_field() { //~^ ERROR: recursive type assert::is_maybe_transmutable::<ExplicitlyPadded, ()>(); - //~^ ERROR: cannot be safely transmuted } diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr index ebfb5361143..bdf2d3b6a58 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr @@ -12,25 +12,10 @@ LL | struct ExplicitlyPadded(Box<ExplicitlyPadded>); error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` | = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again - = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::BikeshedIntrinsicFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, core::mem::transmutability::Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` + = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, core::mem::transmutability::Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` - --> $DIR/transmute_infinitely_recursive_type.rs:24:55 - | -LL | assert::is_maybe_transmutable::<ExplicitlyPadded, ()>(); - | ^^ analyzing the transmutability of `ExplicitlyPadded` is not yet supported - | -note: required by a bound in `is_maybe_transmutable` - --> $DIR/transmute_infinitely_recursive_type.rs:14:14 - | -LL | pub fn is_maybe_transmutable<Src, Dst>() - | --------------------- required by a bound in this function -LL | where -LL | Dst: BikeshedIntrinsicFrom<Src>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0072, E0277, E0391. +Some errors have detailed explanations: E0072, E0391. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/transmutability/structs/should_order_fields_correctly.rs b/tests/ui/transmutability/structs/should_order_fields_correctly.rs index 3675e4330ec..aa9ca39eff2 100644 --- a/tests/ui/transmutability/structs/should_order_fields_correctly.rs +++ b/tests/ui/transmutability/structs/should_order_fields_correctly.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/transmute-padding-ice.rs b/tests/ui/transmutability/transmute-padding-ice.rs index f5935a0009e..133241c89cb 100644 --- a/tests/ui/transmutability/transmute-padding-ice.rs +++ b/tests/ui/transmutability/transmute-padding-ice.rs @@ -9,11 +9,11 @@ use std::mem::size_of; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs index 7524922c16a..74f7a1a2e89 100644 --- a/tests/ui/transmutability/uninhabited.rs +++ b/tests/ui/transmutability/uninhabited.rs @@ -3,11 +3,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 88a98c798fc..3fa02f0867c 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -34,7 +34,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -56,7 +56,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -78,7 +78,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -100,7 +100,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs index c829f83149e..838643defd5 100644 --- a/tests/ui/transmutability/unions/boolish.rs +++ b/tests/ui/transmutability/unions/boolish.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/unions/repr/should_handle_align.rs b/tests/ui/transmutability/unions/repr/should_handle_align.rs index ba4e904e161..0605651bd7b 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_align.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/repr/should_handle_all.rs b/tests/ui/transmutability/unions/repr/should_handle_all.rs index 85d48dd9b7f..8505c7f9123 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_all.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_all.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/repr/should_handle_packed.rs b/tests/ui/transmutability/unions/repr/should_handle_packed.rs index fc06eba4353..5e9851ab0c9 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_packed.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_packed.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/should_pad_variants.rs b/tests/ui/transmutability/unions/should_pad_variants.rs index 1e4d2db8f74..986c7fafb85 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.rs +++ b/tests/ui/transmutability/unions/should_pad_variants.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr index da4294bdbce..bb26281c2f0 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.stderr +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) 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 index 7efe9ac70f1..359ba515439 100644 --- 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 @@ -7,11 +7,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.rs b/tests/ui/transmutability/unions/should_reject_contraction.rs index 62a0ee92919..87398328fc7 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.rs +++ b/tests/ui/transmutability/unions/should_reject_contraction.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr index 20eaa3a6b09..ea68de14efc 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.stderr +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.rs b/tests/ui/transmutability/unions/should_reject_disjoint.rs index 732f92e8160..0427e3c44a2 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.rs +++ b/tests/ui/transmutability/unions/should_reject_disjoint.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr index ea47797c970..d55abbe0817 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.stderr +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_disjoint.rs:33:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.rs b/tests/ui/transmutability/unions/should_reject_intersecting.rs index 752a606c861..9b3b18919f5 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.rs +++ b/tests/ui/transmutability/unions/should_reject_intersecting.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> // validity is NOT assumed -----^^^^^^^^^^^^^^^^^^ {} } diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr index 79dec659d9d..522681d7d15 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.stderr +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_intersecting.rs:36:34 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr index d22117165c1..311e8076ed4 100644 --- a/tests/ui/try-trait/try-operator-on-main.stderr +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -14,9 +14,7 @@ LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> { LL | // error for a `Try` type on a non-`Try` fn ... LL | try_trait_generic::<()>(); -LL + LL + Ok(()) -LL + } | error[E0277]: the `?` operator can only be applied to values that implement `Try` diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index ba52eaa0359..113f6a4cc44 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -5,21 +5,21 @@ trait Captures<'a> {} impl<T> Captures<'_> for T {} -type NotCapturedEarly<'a> = impl Sized; //~ [*, o] +type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o] +type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, o, o] +type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [*, o, o] +type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ ['a: *, 'b: o, 'a: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o] +type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR ['a: *, 'b: *, T: o, 'a: o, 'b: o] //~^ ERROR: unconstrained opaque type trait Foo<'i> { @@ -31,24 +31,24 @@ trait Foo<'i> { } impl<'i> Foo<'i> for &'i () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { - type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o] + type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o] //~^ ERROR: unconstrained opaque type } @@ -59,15 +59,15 @@ impl<'a> Nesting<'a> for &'a () { type Output = &'a (); } type NestedDeeply<'a> = - impl Nesting< //~ [*, o] + impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ [*, o] + Output = impl Nesting< //~ ['a: *, 'a: o] 'a, - Output = impl Nesting<'a> //~ [*, o] + Output = impl Nesting<'a> //~ ['a: *, 'a: o] > >, >, diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index e5ced7a4981..489dfe03d44 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -110,73 +110,73 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:8:29 | LL | type NotCapturedEarly<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:11:26 | LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:14:56 | LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; | ^^^^^^^^^^ -error: [*, o, o] +error: ['a: *, 'b: o, 'a: o] --> $DIR/variance.rs:18:49 | LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o, o] +error: ['a: *, 'b: *, T: o, 'a: o, 'b: o] --> $DIR/variance.rs:22:27 | LL | type Bar<'a, 'b: 'b, T> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:34:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:37:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:40:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:45:32 | LL | type ImplicitCapture<'a> = impl Sized; | ^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:48:42 | LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, *, o, o] +error: ['i: *, 'a: *, 'a: o, 'i: o] --> $DIR/variance.rs:51:39 | LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:62:5 | LL | / impl Nesting< @@ -188,7 +188,7 @@ LL | | >, LL | | >; | |_____^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:64:18 | LL | Output = impl Nesting< @@ -201,7 +201,7 @@ LL | | >, LL | | >, | |_________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:66:22 | LL | Output = impl Nesting< @@ -214,7 +214,7 @@ LL | | > LL | | >, | |_____________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:68:26 | LL | Output = impl Nesting< @@ -224,7 +224,7 @@ LL | | Output = impl Nesting<'a> LL | | > | |_________________^ -error: [*, o] +error: ['a: *, 'a: o] --> $DIR/variance.rs:70:30 | LL | Output = impl Nesting<'a> diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs index 9fc249198d0..92c1999e154 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs @@ -3,16 +3,18 @@ // of an impl fn produces a type mismatch error instead of triggering // a const eval cycle - trait Trait { - fn func<const N: u32>() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize` + fn func<const N: u32>() -> [(); N]; + //~^ ERROR: the constant `N` is not of type `usize` + //~| ERROR: mismatched types } struct S {} #[allow(unused_braces)] impl Trait for S { - fn func<const N: u32>() -> [ (); { () }] { //~ ERROR mismatched types + fn func<const N: u32>() -> [(); { () }] { + //~^ ERROR mismatched types N } } diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr index bff926a2081..bb8025d47a1 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr @@ -1,15 +1,21 @@ error[E0308]: mismatched types - --> $DIR/const-in-impl-fn-return-type.rs:15:40 + --> $DIR/const-in-impl-fn-return-type.rs:16:39 | -LL | fn func<const N: u32>() -> [ (); { () }] { - | ^^ expected `usize`, found `()` +LL | fn func<const N: u32>() -> [(); { () }] { + | ^^ expected `usize`, found `()` error: the constant `N` is not of type `usize` - --> $DIR/const-in-impl-fn-return-type.rs:8:32 + --> $DIR/const-in-impl-fn-return-type.rs:7:32 | -LL | fn func<const N: u32>() -> [ (); N ]; - | ^^^^^^^^^ expected `usize`, found `u32` +LL | fn func<const N: u32>() -> [(); N]; + | ^^^^^^^ expected `usize`, found `u32` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/const-in-impl-fn-return-type.rs:7:37 + | +LL | fn func<const N: u32>() -> [(); N]; + | ^ expected `usize`, found `u32` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsized/unsized6.stderr b/tests/ui/unsized/unsized6.stderr index 56e7f60f9ff..d406120efc5 100644 --- a/tests/ui/unsized/unsized6.stderr +++ b/tests/ui/unsized/unsized6.stderr @@ -123,6 +123,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 @@ -177,6 +182,11 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x2; +LL + let y = x2; + | error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs index 6a44a94df3f..97edb7e266a 100644 --- a/tests/ui/variance/variance-associated-consts.rs +++ b/tests/ui/variance/variance-associated-consts.rs @@ -10,7 +10,7 @@ trait Trait { } #[rustc_variance] -struct Foo<T: Trait> { //~ ERROR [o] +struct Foo<T: Trait> { //~ ERROR [T: o] field: [u8; <T as Trait>::Const] //~^ ERROR: unconstrained generic constant } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index b955a7686c2..5c3ed93464a 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -9,7 +9,7 @@ help: try adding a `where` bound LL | struct Foo<T: Trait> where [(); <T as Trait>::Const]: { | ++++++++++++++++++++++++++++++++ -error: [o] +error: [T: o] --> $DIR/variance-associated-consts.rs:13:1 | LL | struct Foo<T: Trait> { diff --git a/tests/ui/variance/variance-associated-types.rs b/tests/ui/variance/variance-associated-types.rs index ecb0821827d..07ff41062e8 100644 --- a/tests/ui/variance/variance-associated-types.rs +++ b/tests/ui/variance/variance-associated-types.rs @@ -10,12 +10,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR [+, +] +struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +] field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR [o, o] +struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o] field: <T as Trait<'a>>::Type } diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr index 70cb246f6e9..ca010b7e7ef 100644 --- a/tests/ui/variance/variance-associated-types.stderr +++ b/tests/ui/variance/variance-associated-types.stderr @@ -1,10 +1,10 @@ -error: [+, +] +error: ['a: +, T: +] --> $DIR/variance-associated-types.rs:13:1 | LL | struct Foo<'a, T : Trait<'a>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: ['a: o, T: o] --> $DIR/variance-associated-types.rs:18:1 | LL | struct Bar<'a, T : Trait<'a>> { diff --git a/tests/ui/variance/variance-object-types.rs b/tests/ui/variance/variance-object-types.rs index 6ded24cd1e9..fd03dec9824 100644 --- a/tests/ui/variance/variance-object-types.rs +++ b/tests/ui/variance/variance-object-types.rs @@ -4,7 +4,7 @@ // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR [o] +struct Foo<'a> { //~ ERROR ['a: o] x: Box<dyn Fn(i32) -> &'a i32 + 'static> } diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr index 963f3454e1b..a6fb9b2403a 100644 --- a/tests/ui/variance/variance-object-types.stderr +++ b/tests/ui/variance/variance-object-types.stderr @@ -1,4 +1,4 @@ -error: [o] +error: ['a: o] --> $DIR/variance-object-types.rs:7:1 | LL | struct Foo<'a> { diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index f1763c403f1..2bcacec33ea 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -6,7 +6,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] +struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +] x: &'a isize, y: &'b [isize], c: &'c str @@ -15,7 +15,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] +struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -24,7 +24,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR [+, o] +struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut &'b isize, } @@ -32,7 +32,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR [+, o] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR [-, o] +struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o] x: extern "Rust" fn(&'a mut &'b isize), } @@ -42,14 +42,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR [-, o] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR [+, o] +struct Test6<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR [*] +struct Test7<'a> { //~ ERROR ['a: *] //~^ ERROR: `'a` is never used x: isize } @@ -57,7 +57,7 @@ struct Test7<'a> { //~ ERROR [*] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR [-, +, o] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index edfc888f656..45ce0303fb2 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -6,43 +6,43 @@ LL | struct Test7<'a> { | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error: [+, +, +] +error: ['a: +, 'b: +, 'c: +] --> $DIR/variance-regions-direct.rs:9:1 | LL | struct Test2<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, -, -] +error: ['a: -, 'b: -, 'c: -] --> $DIR/variance-regions-direct.rs:18:1 | LL | struct Test3<'a, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:27:1 | LL | struct Test4<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, o] +error: ['a: -, 'b: o] --> $DIR/variance-regions-direct.rs:35:1 | LL | struct Test5<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: ['a: +, 'b: o] --> $DIR/variance-regions-direct.rs:45:1 | LL | struct Test6<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [*] +error: ['a: *] --> $DIR/variance-regions-direct.rs:52:1 | LL | struct Test7<'a> { | ^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-direct.rs:60:1 | LL | enum Test8<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 31e25641d8c..aaa4d3f8779 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *] //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -13,25 +13,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR ['w: *, 'x: o, 'y: +, 'z: -] //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR ['a: o, 'b: o, 'c: *] //~^ ERROR: `'c` is never used 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, +, *] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR ['a: o, 'b: +, 'c: *] //~^ ERROR: `'c` is never used 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] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] f: Base<'a, 'b, 'c, 'a> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index 901ec0c6a76..ed839b32350 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -30,31 +30,31 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` -error: [-, +, o, *] +error: ['a: -, 'b: +, 'c: o, 'd: *] --> $DIR/variance-regions-indirect.rs:8:1 | LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, +, -] +error: ['w: *, 'x: o, 'y: +, 'z: -] --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o, *] +error: ['a: o, 'b: o, 'c: *] --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, +, *] +error: ['a: o, 'b: +, 'c: *] --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [-, +, o] +error: ['a: -, 'b: +, 'c: o] --> $DIR/variance-regions-indirect.rs:34:1 | LL | struct Derived4<'a, 'b, 'c:'b> { diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index 25a01b160dd..f86fa2bbef7 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -13,24 +13,24 @@ trait Setter<T> { } #[rustc_variance] -struct TestStruct<U,T:Setter<U>> { //~ ERROR [+, +] +struct TestStruct<U,T:Setter<U>> { //~ ERROR [U: +, T: +] t: T, u: U } #[rustc_variance] -enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +] +enum TestEnum<U,T:Setter<U>> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] -struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +] +struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } #[rustc_variance] -struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [*, +] +struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [U: *, T: +] //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 95ed18c1ad2..49cee3cbeca 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -25,25 +25,25 @@ LL | struct TestBox<U,T:Getter<U>+Setter<U>> { = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead -error: [+, +] +error: [U: +, T: +] --> $DIR/variance-trait-bounds.rs:16:1 | LL | struct TestStruct<U,T:Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:21:1 | LL | enum TestEnum<U,T:Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct<U,T:Setter<U>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [U: *, T: +] --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox<U,T:Getter<U>+Setter<U>> { diff --git a/tests/ui/variance/variance-trait-object-bound.rs b/tests/ui/variance/variance-trait-object-bound.rs index 11303c46520..ca80c6b6dce 100644 --- a/tests/ui/variance/variance-trait-object-bound.rs +++ b/tests/ui/variance/variance-trait-object-bound.rs @@ -11,7 +11,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR [+] +struct TOption<'a> { //~ ERROR ['a: +] v: Option<Box<dyn T + 'a>>, } diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr index f0471a34619..0af21ec12cc 100644 --- a/tests/ui/variance/variance-trait-object-bound.stderr +++ b/tests/ui/variance/variance-trait-object-bound.stderr @@ -1,4 +1,4 @@ -error: [+] +error: ['a: +] --> $DIR/variance-trait-object-bound.rs:14:1 | LL | struct TOption<'a> { diff --git a/tests/ui/variance/variance-types-bounds.rs b/tests/ui/variance/variance-types-bounds.rs index d1814dd97a0..f4738a2dae1 100644 --- a/tests/ui/variance/variance-types-bounds.rs +++ b/tests/ui/variance/variance-types-bounds.rs @@ -4,24 +4,24 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm<A, B> { //~ ERROR [+, +] +struct TestImm<A, B> { //~ ERROR [A: +, B: +] x: A, y: B, } #[rustc_variance] -struct TestMut<A, B:'static> { //~ ERROR [+, o] +struct TestMut<A, B:'static> { //~ ERROR [A: +, B: o] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect<A:'static, B:'static> { //~ ERROR [+, o] +struct TestIndirect<A:'static, B:'static> { //~ ERROR [A: +, B: o] m: TestMut<A, B> } #[rustc_variance] -struct TestIndirect2<A:'static, B:'static> { //~ ERROR [o, o] +struct TestIndirect2<A:'static, B:'static> { //~ ERROR [A: o, B: o] n: TestMut<A, B>, m: TestMut<B, A> } @@ -35,7 +35,7 @@ trait Setter<A> { } #[rustc_variance] -struct TestObject<A, R> { //~ ERROR [o, o] +struct TestObject<A, R> { //~ ERROR [A: o, R: o] n: Box<dyn Setter<A>+Send>, m: Box<dyn Getter<R>+Send>, } diff --git a/tests/ui/variance/variance-types-bounds.stderr b/tests/ui/variance/variance-types-bounds.stderr index bb816443476..408c2ae8d36 100644 --- a/tests/ui/variance/variance-types-bounds.stderr +++ b/tests/ui/variance/variance-types-bounds.stderr @@ -1,28 +1,28 @@ -error: [+, +] +error: [A: +, B: +] --> $DIR/variance-types-bounds.rs:7:1 | LL | struct TestImm<A, B> { | ^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:13:1 | LL | struct TestMut<A, B:'static> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, o] +error: [A: +, B: o] --> $DIR/variance-types-bounds.rs:19:1 | LL | struct TestIndirect<A:'static, B:'static> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, B: o] --> $DIR/variance-types-bounds.rs:24:1 | LL | struct TestIndirect2<A:'static, B:'static> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o] +error: [A: o, R: o] --> $DIR/variance-types-bounds.rs:38:1 | LL | struct TestObject<A, R> { diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs index cfc03b75473..aa336d1b424 100644 --- a/tests/ui/variance/variance-types.rs +++ b/tests/ui/variance/variance-types.rs @@ -7,32 +7,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [+, o, o] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell<A> { //~ ERROR [o] +struct InvariantCell<A> { //~ ERROR [A: o] t: Cell<A> } #[rustc_variance] -struct InvariantIndirect<A> { //~ ERROR [o] +struct InvariantIndirect<A> { //~ ERROR [A: o] t: InvariantCell<A> } #[rustc_variance] -struct Covariant<A> { //~ ERROR [+] +struct Covariant<A> { //~ ERROR [A: +] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant<A> { //~ ERROR [-] +struct Contravariant<A> { //~ ERROR [A: -] t: fn(A) } #[rustc_variance] -enum Enum<A,B,C> { //~ ERROR [+, -, o] +enum Enum<A,B,C> { //~ ERROR [A: +, B: -, C: o] Foo(Covariant<A>), Bar(Contravariant<B>), Zed(Covariant<C>,Contravariant<C>) diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr index 0fda4b8036e..f2a67949425 100644 --- a/tests/ui/variance/variance-types.stderr +++ b/tests/ui/variance/variance-types.stderr @@ -1,34 +1,34 @@ -error: [+, o, o] +error: ['a: +, A: o, B: o] --> $DIR/variance-types.rs:10:1 | LL | struct InvariantMut<'a,A:'a,B:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:15:1 | LL | struct InvariantCell<A> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [o] +error: [A: o] --> $DIR/variance-types.rs:20:1 | LL | struct InvariantIndirect<A> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [+] +error: [A: +] --> $DIR/variance-types.rs:25:1 | LL | struct Covariant<A> { | ^^^^^^^^^^^^^^^^^^^ -error: [-] +error: [A: -] --> $DIR/variance-types.rs:30:1 | LL | struct Contravariant<A> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [+, -, o] +error: [A: +, B: -, C: o] --> $DIR/variance-types.rs:35:1 | LL | enum Enum<A,B,C> { diff --git a/triagebot.toml b/triagebot.toml index 161fe98fca9..d7bc60e6c6f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -913,7 +913,7 @@ cc = ["@kobzol"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jhpratt", "oli-obk"] +users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "kobzol"] [assign.adhoc_groups] compiler-team = [ @@ -951,6 +951,7 @@ libs = [ "@joboet", "@jhpratt", "@tgross35", + "@thomcc", ] bootstrap = [ "@Mark-Simulacrum", |
