diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 364a6a035ab88..bedc6ca11b3f6 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6badd29091750..3f75cce009225 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -605,6 +605,8 @@ hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = hir_analysis_unused_generic_parameter_ty_alias_help = consider removing `{$param_name}` or referring to it in the body of the type alias +hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type + hir_analysis_value_of_associated_struct_already_specified = the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified .label = re-bound here diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 09320b8687836..f2331f3fd8e13 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -992,6 +992,32 @@ fn check_impl_items_against_trait<'tcx>( let trait_def = tcx.trait_def(trait_ref.def_id); + let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); + + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id); + let param_env = tcx.param_env(impl_id); + + let self_is_guaranteed_unsized = match tcx + .struct_tail_raw( + trait_ref.self_ty(), + |ty| { + ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| { + Ty::new_error_with_message( + tcx, + tcx.def_span(impl_id), + "struct tail should be computable", + ) + }) + }, + || (), + ) + .kind() + { + ty::Dynamic(_, _, ty::DynKind::Dyn) | ty::Slice(_) | ty::Str => true, + _ => false, + }; + for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id { @@ -1021,6 +1047,15 @@ fn check_impl_items_against_trait<'tcx>( } } + if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) { + tcx.emit_node_span_lint( + rustc_lint_defs::builtin::DEAD_CODE, + tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()), + tcx.def_span(ty_impl_item.def_id), + errors::UselessImplItem, + ) + } + check_specialization_validity( tcx, trait_def, @@ -1044,7 +1079,11 @@ fn check_impl_items_against_trait<'tcx>( .as_ref() .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value()); - if !is_implemented && tcx.defaultness(impl_id).is_final() { + if !is_implemented + && tcx.defaultness(impl_id).is_final() + // unsized types don't need to implement methods that have `Self: Sized` bounds. + && !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id)) + { missing_items.push(tcx.associated_item(trait_item_id)); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 99262f9871e07..852533ff5c954 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -908,6 +908,10 @@ pub(crate) enum ImplNotMarkedDefault { }, } +#[derive(LintDiagnostic)] +#[diag(hir_analysis_useless_impl_item)] +pub(crate) struct UselessImplItem; + #[derive(Diagnostic)] #[diag(hir_analysis_missing_trait_item, code = E0046)] pub(crate) struct MissingTraitItem { diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index a39bb884faadc..141d261b5f015 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -68,9 +68,7 @@ cfg_match! { const CHUNK_SIZE: usize = 16; - let src_bytes = src.as_bytes(); - - let chunk_count = src.len() / CHUNK_SIZE; + let (chunks, tail) = src.as_bytes().as_chunks::(); // This variable keeps track of where we should start decoding a // chunk. If a multi-byte character spans across chunk boundaries, @@ -78,11 +76,10 @@ cfg_match! { // handled it. let mut intra_chunk_offset = 0; - for chunk_index in 0..chunk_count { - let ptr = src_bytes.as_ptr() as *const __m128i; + for (chunk_index, chunk) in chunks.iter().enumerate() { // We don't know if the pointer is aligned to 16 bytes, so we // use `loadu`, which supports unaligned loading. - let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) }; + let chunk = unsafe { _mm_loadu_si128(chunk.as_ptr() as *const __m128i) }; // For character in the chunk, see if its byte value is < 0, which // indicates that it's part of a UTF-8 char. @@ -123,7 +120,7 @@ cfg_match! { } // There might still be a tail left to analyze - let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset; + let tail_start = src.len() - tail.len() + intra_chunk_offset; if tail_start < src.len() { analyze_source_file_generic( &src[tail_start..], diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c09669d959c93..bca9323a50d4c 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -31,6 +31,7 @@ #![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(slice_as_chunks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/library/Cargo.lock b/library/Cargo.lock index 0ad56f3ce47ab..de9685742f59f 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.147" +version = "0.1.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170335a76fbcba350c3ea795c15df3b2c02934e35e502e82c4dd7837d4d0161" +checksum = "26137996631d90d2727b905b480fdcf8c4479fdbce7afd7f8e3796d689b33cc2" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 6f9074d91b01d..9e80f3579e808 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.9.0", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index a0a28e8079601..f4d4894c1bbdf 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,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.147" } +compiler_builtins = { version = "=0.1.148" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index a47f3af60cbd5..890e64e2babbc 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -88,9 +88,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.0" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" dependencies = [ "shlex", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index ed51862390d40..2c1d85b01e6af 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -37,7 +37,9 @@ test = false # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); # otherwise, some targets will fail. That's why these dependencies are explicitly pinned. -cc = "=1.2.0" +# +# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed. +cc = "=1.1.22" cmake = "=0.1.48" build_helper = { path = "../build_helper" } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index d335ce65ad53c..02d6f205d8025 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -293,17 +293,27 @@ impl Step for Cargo { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Cargo { stage: run.builder.top_stage, host: run.target }); + // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2 + // as tests for this step don't work with a lower stage. + let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 { + run.builder.top_stage + } else { + 2 + }; + + run.builder.ensure(Cargo { stage, host: run.target }); } /// Runs `cargo test` for `cargo` packaged with Rust. fn run(self, builder: &Builder<'_>) { - if self.stage < 2 { - eprintln!("WARNING: cargo tests on stage {} may not behave well.", self.stage); + let stage = self.stage; + + if stage < 2 { + eprintln!("WARNING: cargo tests on stage {stage} may not behave well."); eprintln!("HELP: consider using stage 2"); } - let compiler = builder.compiler(self.stage, self.host); + let compiler = builder.compiler(stage, self.host); let cargo = builder.ensure(tool::Cargo { compiler, target: self.host }); let compiler = cargo.build_compiler; @@ -340,7 +350,7 @@ impl Step for Cargo { crates: vec!["cargo".into()], target: self.host.triple.to_string(), host: self.host.triple.to_string(), - stage: self.stage, + stage, }, builder, ); @@ -739,7 +749,15 @@ impl Step for Clippy { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Clippy { stage: run.builder.top_stage, host: run.target }); + // If stage is explicitly set or not lower than 2, keep it. Otherwise, make sure it's at least 2 + // as tests for this step don't work with a lower stage. + let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 { + run.builder.top_stage + } else { + 2 + }; + + run.builder.ensure(Clippy { stage, host: run.target }); } /// Runs `cargo test` for clippy. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index d4b72ead045eb..2be42f16e2ab6 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -218,6 +218,8 @@ pub struct Config { pub stderr_is_tty: bool, pub on_fail: Option, + pub explicit_stage_from_cli: bool, + pub explicit_stage_from_config: bool, pub stage: u32, pub keep_stage: Vec, pub keep_stage_std: Vec, @@ -2323,6 +2325,14 @@ impl Config { config.compiletest_diff_tool = compiletest_diff_tool; let download_rustc = config.download_rustc_commit.is_some(); + config.explicit_stage_from_cli = flags.stage.is_some(); + config.explicit_stage_from_config = test_stage.is_some() + || build_stage.is_some() + || doc_stage.is_some() + || dist_stage.is_some() + || install_stage.is_some() + || check_stage.is_some() + || bench_stage.is_some(); // See https://github.com/rust-lang/compiler-team/issues/326 config.stage = match config.cmd { Subcommand::Check { .. } => flags.stage.or(check_stage).unwrap_or(0), @@ -2392,6 +2402,10 @@ impl Config { } } + pub fn is_explicit_stage(&self) -> bool { + self.explicit_stage_from_cli || self.explicit_stage_from_config + } + /// Runs a command, printing out nice contextual information if it fails. /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index f0a185ee3a7eb..eff5e0337428c 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -454,3 +454,64 @@ fn check_rustc_if_unchanged_paths() { assert!(config.src.join(p).exists(), "{p} doesn't exist."); } } + +#[test] +fn test_explicit_stage() { + let config = Config::parse_inner( + Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]), + |&_| { + toml::from_str( + r#" + [build] + test-stage = 1 + "#, + ) + }, + ); + + assert!(!config.explicit_stage_from_cli); + assert!(config.explicit_stage_from_config); + assert!(config.is_explicit_stage()); + + let config = Config::parse_inner( + Flags::parse(&[ + "check".to_owned(), + "--stage=2".to_owned(), + "--config=/does/not/exist".to_owned(), + ]), + |&_| toml::from_str(""), + ); + + assert!(config.explicit_stage_from_cli); + assert!(!config.explicit_stage_from_config); + assert!(config.is_explicit_stage()); + + let config = Config::parse_inner( + Flags::parse(&[ + "check".to_owned(), + "--stage=2".to_owned(), + "--config=/does/not/exist".to_owned(), + ]), + |&_| { + toml::from_str( + r#" + [build] + test-stage = 1 + "#, + ) + }, + ); + + assert!(config.explicit_stage_from_cli); + assert!(config.explicit_stage_from_config); + assert!(config.is_explicit_stage()); + + let config = Config::parse_inner( + Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]), + |&_| toml::from_str(""), + ); + + assert!(!config.explicit_stage_from_cli); + assert!(!config.explicit_stage_from_config); + assert!(!config.is_explicit_stage()); +} diff --git a/src/tools/cargo b/src/tools/cargo index ce948f4616e3d..1d1d646c06a84 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ce948f4616e3d4277e30c75c8bb01e094910df39 +Subproject commit 1d1d646c06a84c1aa53967b394b7f1218f85db82 diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr index b0c493faf1ef2..23341ec6bdc27 100644 --- a/tests/ui/did_you_mean/recursion_limit_deref.stderr +++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr @@ -1,3 +1,7 @@ +error: reached the recursion limit finding the struct tail for `K` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` + error: reached the recursion limit finding the struct tail for `Bottom` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` @@ -21,7 +25,7 @@ LL | let x: &Bottom = &t; = note: expected reference `&Bottom` found reference `&Top` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0055, E0308. For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/invalid/issue-114435-layout-type-err.rs b/tests/ui/invalid/issue-114435-layout-type-err.rs index f68744a13c156..2a86839e416f6 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.rs +++ b/tests/ui/invalid/issue-114435-layout-type-err.rs @@ -1,6 +1,6 @@ -//@ build-fail +//@ check-fail //@ compile-flags: --crate-type lib -Cdebuginfo=2 -//@ error-pattern: the type has an unknown layout +//@ error-pattern: recursion limit #![recursion_limit = "10"] macro_rules! link { @@ -28,7 +28,6 @@ impl Bottom { } } - link!(A, B); link!(B, C); link!(C, D); @@ -41,4 +40,4 @@ link!(I, J); link!(J, K); link!(K, Bottom); -fn main() { } +fn main() {} diff --git a/tests/ui/invalid/issue-114435-layout-type-err.stderr b/tests/ui/invalid/issue-114435-layout-type-err.stderr index a2db74ff8bd8e..2fddc62f004f9 100644 --- a/tests/ui/invalid/issue-114435-layout-type-err.stderr +++ b/tests/ui/invalid/issue-114435-layout-type-err.stderr @@ -2,7 +2,5 @@ error: reached the recursion limit finding the struct tail for `Bottom` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` -error: the type has an unknown layout - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr new file mode 100644 index 0000000000000..93b064cdce2a5 --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr @@ -0,0 +1,6 @@ +error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index 4fbcbefec913b..729771e560e98 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -1,7 +1,7 @@ // Regression test for #129541 //@ revisions: unique multiple -//@ check-pass +//@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` trait Bound {} trait Normalize { diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr new file mode 100644 index 0000000000000..93b064cdce2a5 --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr @@ -0,0 +1,6 @@ +error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/trivial_impl_sized.rs b/tests/ui/traits/trivial_impl_sized.rs index 501a3405090e6..59cc079c2682d 100644 --- a/tests/ui/traits/trivial_impl_sized.rs +++ b/tests/ui/traits/trivial_impl_sized.rs @@ -1,5 +1,5 @@ -//! This test checks that we currently need to implement -//! members, even if their where bounds don't hold for the impl type. +//! This test checks that we do not need to implement +//! members, whose `where Self: Sized` bounds don't hold for the impl type. trait Foo { fn foo() @@ -15,12 +15,28 @@ impl Foo for () { impl Foo for i32 {} //~^ ERROR: not all trait items implemented, missing: `foo` -// Should be allowed impl Foo for dyn std::fmt::Debug {} -//~^ ERROR: not all trait items implemented, missing: `foo` +#[deny(dead_code)] impl Foo for dyn std::fmt::Display { fn foo() {} + //~^ ERROR this item cannot be used as its where bounds are not satisfied +} + +struct Struct { + i: i32, + tail: [u8], } +impl Foo for Struct {} + +// Ensure we only allow known-unsized types to be skipped +trait Trait { + fn foo(self) + where + Self: Sized; +} +impl Trait for T {} +//~^ ERROR: not all trait items implemented, missing: `foo` + fn main() {} diff --git a/tests/ui/traits/trivial_impl_sized.stderr b/tests/ui/traits/trivial_impl_sized.stderr index ebf6dfc9dd2df..95cab33718264 100644 --- a/tests/ui/traits/trivial_impl_sized.stderr +++ b/tests/ui/traits/trivial_impl_sized.stderr @@ -9,17 +9,29 @@ LL | | Self: Sized; LL | impl Foo for i32 {} | ^^^^^^^^^^^^^^^^ missing `foo` in implementation +error: this item cannot be used as its where bounds are not satisfied for the `Self` type + --> $DIR/trivial_impl_sized.rs:22:5 + | +LL | fn foo() {} + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/trivial_impl_sized.rs:20:8 + | +LL | #[deny(dead_code)] + | ^^^^^^^^^ + error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/trivial_impl_sized.rs:19:1 + --> $DIR/trivial_impl_sized.rs:39:1 | -LL | / fn foo() +LL | / fn foo(self) LL | | where LL | | Self: Sized; | |____________________- `foo` from trait -... -LL | impl Foo for dyn std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation +LL | } +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0046`.