diff --git a/.mailmap b/.mailmap index 21e1adb43cff9..26d6be9f0c600 100644 --- a/.mailmap +++ b/.mailmap @@ -429,6 +429,8 @@ Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> nils <48135649+Nilstrieb Nif Ward Nika Layzell NODA Kai +Oğuz Ağcayazı +Oğuz Ağcayazı oliver <16816606+o752d@users.noreply.github.com> Oliver Middleton Oliver Scherer diff --git a/Cargo.lock b/Cargo.lock index 2ba0a9b895cd4..476f5578187b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6030,19 +6030,21 @@ dependencies = [ [[package]] name = "windows-bindgen" -version = "0.49.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6935fb09b84ee57929ae92518b475f5dfdfbeb87c5334756acc28ee8e202b60" +checksum = "bc1f16b778125675feee0d15d6dd9f6af0e3ac52b3233d63a10aa39230c1cd75" dependencies = [ + "proc-macro2", + "rayon", + "syn 2.0.29", "windows-metadata", - "windows-tokens", ] [[package]] name = "windows-metadata" -version = "0.49.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5bca94a32bf1e6a376522b6601275a3b611ee885ec0f1b6a05f17e8cfd3385" +checksum = "753135d996f9da437c0b31dbde3032489a61708361929bcc07d4fba0b161000e" [[package]] name = "windows-sys" @@ -6092,12 +6094,6 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] -[[package]] -name = "windows-tokens" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34c9a3b28cb41db7385546f7f9a8179348dffc89923dde66857b1ba5312f6b4" - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 2ea399789b9a3..27072a60f65f0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -245,7 +245,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; diag.span_note( *trait_span, - format!("due to current limitations in the borrow checker, this implies a `'static` lifetime") + "due to current limitations in the borrow checker, this implies a `'static` lifetime" ); let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) else { return; }; let Def(_, trait_res_defid) = trait_ref.path.res else { return; }; @@ -277,7 +277,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - format!("consider restricting the type parameter to the `'static` lifetime"), + "consider restricting the type parameter to the `'static` lifetime", suggestions, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 9b5a6b89191e1..6d55fdc307401 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -875,7 +875,7 @@ pub(crate) fn codegen_place<'tcx>( PlaceElem::Deref => { cplace = cplace.place_deref(fx); } - PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty), + PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"), PlaceElem::Field(field, _ty) => { cplace = cplace.place_field(fx, field); } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index c64a4008996d5..6efbe14986354 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -21,7 +21,7 @@ fn report_simd_type_validation_error( pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, - _args: GenericArgsRef<'tcx>, + generic_args: GenericArgsRef<'tcx>, args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, target: BasicBlock, @@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } + // simd_shuffle_generic(x: T, y: T) -> U + sym::simd_shuffle_generic => { + let [x, y] = args else { + bug!("wrong number of args for intrinsic {intrinsic}"); + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + + if !x.layout().ty.is_simd() { + report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); + return; + } + + let idx = generic_args[2] + .expect_const() + .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(span)) + .unwrap() + .unwrap_branch(); + + assert_eq!(x.layout(), y.layout()); + let layout = x.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + + assert_eq!(lane_ty, ret_lane_ty); + assert_eq!(idx.len() as u64, ret_lane_count); + + let total_len = lane_count * 2; + + let indexes = + idx.iter().map(|idx| idx.unwrap_leaf().try_to_u16().unwrap()).collect::>(); + + for &idx in &indexes { + assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len); + } + + for (out_idx, in_idx) in indexes.into_iter().enumerate() { + let in_lane = if u64::from(in_idx) < lane_count { + x.value_lane(fx, in_idx.into()) + } else { + y.value_lane(fx, u64::from(in_idx) - lane_count) + }; + let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); + out_lane.write_cvalue(fx, in_lane); + } + } + // simd_shuffle(x: T, y: T, idx: I) -> U sym::simd_shuffle => { let (x, y, idx) = match args { diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index ff95141ce90fb..d4273c0b593ac 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -674,14 +674,6 @@ impl<'tcx> CPlace<'tcx> { } } - pub(crate) fn place_opaque_cast( - self, - fx: &mut FunctionCx<'_, '_, 'tcx>, - ty: Ty<'tcx>, - ) -> CPlace<'tcx> { - CPlace { inner: self.inner, layout: fx.layout_of(ty) } - } - pub(crate) fn place_field( self, fx: &mut FunctionCx<'_, '_, 'tcx>, diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index ddaff36f24b1d..c0cfe39f1e0a4 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -37,6 +37,8 @@ codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and s codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` +codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto` + codegen_llvm_missing_features = add the missing features in a `target_feature` attribute diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index ba263296bb454..cb5acf79135cc 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -2,7 +2,7 @@ use crate::back::write::{ self, bitcode_section_name, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers, }; use crate::errors::{ - DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, + DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro, }; use crate::llvm::{self, build_string}; use crate::{LlvmCodegenBackend, ModuleLlvm}; @@ -36,8 +36,12 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { - CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true, - CrateType::Rlib | CrateType::ProcMacro => false, + CrateType::Executable + | CrateType::Dylib + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::ProcMacro => true, + CrateType::Rlib => false, } } @@ -87,6 +91,11 @@ fn prepare_lto( diag_handler.emit_err(LtoDylib); return Err(FatalError); } + } else if *crate_type == CrateType::ProcMacro { + if !cgcx.opts.unstable_opts.dylib_lto { + diag_handler.emit_err(LtoProcMacro); + return Err(FatalError); + } } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 264c273ba3072..665d195790c2d 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -138,6 +138,10 @@ pub(crate) struct LtoDisallowed; #[diag(codegen_llvm_lto_dylib)] pub(crate) struct LtoDylib; +#[derive(Diagnostic)] +#[diag(codegen_llvm_lto_proc_macro)] +pub(crate) struct LtoProcMacro; + #[derive(Diagnostic)] #[diag(codegen_llvm_lto_bitcode_from_rlib)] pub(crate) struct LtoBitcodeFromRlib { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 9289c37d76352..a97b803fc645b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; @@ -376,7 +376,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { - match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { + match generic_simd_intrinsic( + self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span, + ) { Ok(llval) => llval, Err(()) => return, } @@ -911,6 +913,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, + fn_args: GenericArgsRef<'tcx>, args: &[OperandRef<'tcx, &'ll Value>], ret_ty: Ty<'tcx>, llret_ty: &'ll Type, @@ -1030,6 +1033,56 @@ fn generic_simd_intrinsic<'ll, 'tcx>( )); } + if name == sym::simd_shuffle_generic { + let idx = fn_args[2] + .expect_const() + .eval(tcx, ty::ParamEnv::reveal_all(), Some(span)) + .unwrap() + .unwrap_branch(); + let n = idx.len() as u64; + + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( + out_len == n, + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } + ); + require!( + in_elem == out_ty, + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + ); + + let total_len = in_len * 2; + + let indices: Option> = idx + .iter() + .enumerate() + .map(|(arg_idx, val)| { + let idx = val.unwrap_leaf().try_to_i32().unwrap(); + if idx >= i32::try_from(total_len).unwrap() { + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds { + span, + name, + arg_idx: arg_idx as u64, + total_len: total_len.into(), + }); + None + } else { + Some(bx.const_i32(idx)) + } + }) + .collect(); + let Some(indices) = indices else { + return Ok(bx.const_null(llret_ty)); + }; + + return Ok(bx.shuffle_vector( + args[0].immediate(), + args[1].immediate(), + bx.const_vector(&indices), + )); + } + if name == sym::simd_shuffle { // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index d0a078505d2d4..6f7d7482aea8c 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -46,8 +46,6 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` .note = an unsuffixed integer value, e.g., `1`, is expected -codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a7ac728c59b02..c4a0f6291e7f4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -365,15 +365,9 @@ fn link_rlib<'a>( // loaded from the libraries found here and then encode that into the // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { - let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else { + let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else { continue; }; - if whole_archive == Some(true) - && flavor == RlibFlavor::Normal - && !codegen_results.crate_info.feature_packed_bundled_libs - { - sess.emit_err(errors::IncompatibleLinkingModifiers); - } if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename { let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); let src = read(path).map_err(|e| sess.emit_fatal(errors::ReadFileError {message: e }))?; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 6c51dffedbfad..1e4ea73a1724f 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -181,7 +181,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( old_info } } - (_, &ty::Dynamic(ref data, _, _)) => meth::get_vtable(cx, source, data.principal()), + (_, ty::Dynamic(data, _, _)) => meth::get_vtable(cx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } @@ -857,7 +857,6 @@ impl CrateInfo { dependency_formats: tcx.dependency_formats(()).clone(), windows_subsystem, natvis_debugger_visualizers: Default::default(), - feature_packed_bundled_libs: tcx.features().packed_bundled_libs, }; let crates = tcx.crates(()); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index bfd572a2eeafe..14311ec08fd26 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -107,10 +107,6 @@ pub struct CreateTempDir { pub error: Error, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_incompatible_linking_modifiers)] -pub struct IncompatibleLinkingModifiers; - #[derive(Diagnostic)] #[diag(codegen_ssa_add_native_library)] pub struct AddNativeLibrary { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 7ebaca9b0bc60..f6186a290f81f 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -164,7 +164,6 @@ pub struct CrateInfo { pub dependency_formats: Lrc, pub windows_subsystem: Option, pub natvis_debugger_visualizers: BTreeSet, - pub feature_packed_bundled_libs: bool, // unstable feature flag. } #[derive(Encodable, Decodable)] diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index a9ecbdc5f35ed..f775711f87020 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -463,7 +463,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ProjectionElem::Field(ref field, _) => { cg_base.project_field(bx, field.index()) } - mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty), + mir::ProjectionElem::OpaqueCast(ty) => { + bug!("encountered OpaqueCast({ty}) in codegen") + } mir::ProjectionElem::Index(index) => { let index = &mir::Operand::Copy(mir::Place::from(index)); let index = self.codegen_operand(bx, index); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 6c720ac4a574d..f462c13816ee8 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -316,7 +316,9 @@ where { use rustc_middle::mir::ProjectionElem::*; Ok(match proj_elem { - OpaqueCast(ty) => base.transmute(self.layout_of(ty)?, self)?, + OpaqueCast(ty) => { + span_bug!(self.cur_span(), "OpaqueCast({ty}) encountered after borrowck") + } Field(field, _) => self.project_field(base, field.index())?, Downcast(_, variant) => self.project_downcast(base, variant)?, Deref => self.deref_pointer(&base.to_op(self)?)?.into(), diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0d8733070a446..18b22882e7d08 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -633,6 +633,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location: Location, ) { match elem { + ProjectionElem::OpaqueCast(ty) + if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) => + { + self.fail( + location, + format!("explicit opaque type cast to `{ty}` after `RevealAll`"), + ) + } ProjectionElem::Index(index) => { let index_ty = self.body.local_decls[index].ty; if index_ty != self.tcx.types.usize { diff --git a/compiler/rustc_error_codes/src/error_codes/E0760.md b/compiler/rustc_error_codes/src/error_codes/E0760.md index 85e5faada224e..9c4739f0df084 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0760.md +++ b/compiler/rustc_error_codes/src/error_codes/E0760.md @@ -5,7 +5,7 @@ or `Self` that references lifetimes from a parent scope. Erroneous code example: -```compile_fail,edition2018 +```ignore,edition2018 struct S<'a>(&'a i32); impl<'a> S<'a> { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index afcf30d0b293e..32d8380abd3ab 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -197,6 +197,8 @@ declare_features! ( /// + `impl Iterator for &mut Iterator` /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + /// Allows referencing `Self` and projections in impl-trait. + (accepted, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None), /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), /// Allows inferring outlives requirements (RFC 2093). @@ -267,6 +269,8 @@ declare_features! ( (accepted, non_modrs_mods, "1.30.0", Some(44660), None), /// Allows the use of or-patterns (e.g., `0 | 1`). (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows using `+bundle,+whole-archive` link modifiers with native libs. + (accepted, packed_bundled_libs, "CURRENT_RUSTC_VERSION", Some(108081), None), /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. /// This defines the behavior of panics. (accepted, panic_handler, "1.30.0", Some(44489), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 94afb6edcf6e4..a02c04ecd3ecb 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -241,8 +241,6 @@ declare_features! ( (active, linkage, "1.0.0", Some(29603), None), /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. (internal, needs_panic_runtime, "1.10.0", Some(32837), None), - /// Allows using `+bundled,+whole-archive` native libs. - (active, packed_bundled_libs, "1.69.0", Some(108081), None), /// Allows using the `#![panic_runtime]` attribute. (internal, panic_runtime, "1.10.0", Some(32837), None), /// Allows `extern "platform-intrinsic" { ... }`. @@ -472,8 +470,6 @@ declare_features! ( (active, impl_trait_in_assoc_type, "1.70.0", Some(63063), None), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), - /// Allows referencing `Self` and projections in impl-trait. - (active, impl_trait_projections, "1.67.0", Some(103532), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 2a68d745c7693..1c926533a27fd 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -38,6 +38,17 @@ hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present .label = `for<...>` is here +hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures + +hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions + .note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + .coercions_note = currently, {$number} fields need coercions: {$coercions} + .label = requires multiple coercions + +hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}` + +hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found + hir_analysis_const_bound_for_non_const_trait = ~const can only be applied to `#[const_trait]` traits @@ -61,6 +72,15 @@ hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors +hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions + .note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced + .coercions_note = currently, {$number} fields need coercions: {$coercions} + +hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` + +hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + .note = extra field `{$name}` of type `{$ty}` is not allowed + hir_analysis_drop_impl_negative = negative `Drop` impls are not supported hir_analysis_drop_impl_on_wrong_item = @@ -232,6 +252,8 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures +hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` + hir_analysis_return_type_notation_conflicting_bound = ambiguous associated function `{$assoc_name}` for `{$ty_name}` .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}` @@ -299,6 +321,9 @@ hir_analysis_too_large_static = extern static is too large for the current archi hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` .suggestion = remove this annotation +hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type + .label = this field does not implement `{$trait_name}` + hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eb1f48d23ff77..44e1bdb837070 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,18 +5,15 @@ use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::Visitor; -use rustc_hir::{ItemKind, Node, PathSegment}; -use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor; +use rustc_hir::Node; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; -use rustc_middle::hir::nested_filter; use rustc_middle::middle::stability::EvalResult; use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode}; use rustc_middle::ty::fold::BottomUpFolder; @@ -218,9 +215,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let args = GenericArgs::identity_for_item(tcx, item.owner_id); let span = tcx.def_span(item.owner_id.def_id); - if !tcx.features().impl_trait_projections { - check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span); - } if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() { return; } @@ -231,129 +225,6 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); } -/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result -/// in "inheriting lifetimes". -#[instrument(level = "debug", skip(tcx, span))] -pub(super) fn check_opaque_for_inheriting_lifetimes( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - span: Span, -) { - let item = tcx.hir().expect_item(def_id); - debug!(?item, ?span); - - struct ProhibitOpaqueVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - opaque_identity_ty: Ty<'tcx>, - parent_count: u32, - references_parent_regions: bool, - selftys: Vec<(Span, Option)>, - } - - impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueVisitor<'tcx> { - type BreakTy = Ty<'tcx>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - debug!(?t, "root_visit_ty"); - if t == self.opaque_identity_ty { - ControlFlow::Continue(()) - } else { - t.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { - tcx: self.tcx, - op: |region| { - if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *region - && index < self.parent_count - { - self.references_parent_regions= true; - } - }, - }); - if self.references_parent_regions { - ControlFlow::Break(t) - } else { - ControlFlow::Continue(()) - } - } - } - } - - impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { - match arg.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { - [PathSegment { res: Res::SelfTyParam { .. }, .. }] => { - let impl_ty_name = None; - self.selftys.push((path.span, impl_ty_name)); - } - [PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => { - let impl_ty_name = Some(self.tcx.def_path_str(*def_id)); - self.selftys.push((path.span, impl_ty_name)); - } - _ => {} - }, - _ => {} - } - hir::intravisit::walk_ty(self, arg); - } - } - - if let ItemKind::OpaqueTy(&hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), - .. - }) = item.kind - { - let args = GenericArgs::identity_for_item(tcx, def_id); - let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - let mut visitor = ProhibitOpaqueVisitor { - opaque_identity_ty, - parent_count: tcx.generics_of(def_id).parent_count as u32, - references_parent_regions: false, - tcx, - selftys: vec![], - }; - let prohibit_opaque = tcx - .explicit_item_bounds(def_id) - .instantiate_identity_iter_copied() - .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); - - if let Some(ty) = prohibit_opaque.break_value() { - visitor.visit_item(&item); - let is_async = match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) - } - _ => unreachable!(), - }; - - let mut err = feature_err( - &tcx.sess.parse_sess, - sym::impl_trait_projections, - span, - format!( - "`{}` return type cannot contain a projection or `Self` that references \ - lifetimes from a parent scope", - if is_async { "async fn" } else { "impl Trait" }, - ), - ); - for (span, name) in visitor.selftys { - err.span_suggestion( - span, - "consider spelling out the type instead", - name.unwrap_or_else(|| format!("{ty:?}")), - Applicability::MaybeIncorrect, - ); - } - err.emit(); - } - } -} - /// Checks that an opaque type does not contain cycles. pub(super) fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 3c0d977917fd9..c61719c1fd293 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -20,6 +20,7 @@ fn equate_intrinsic_type<'tcx>( it: &hir::ForeignItem<'_>, n_tps: usize, n_lts: usize, + n_cts: usize, sig: ty::PolyFnSig<'tcx>, ) { let (own_counts, span) = match &it.kind { @@ -51,7 +52,7 @@ fn equate_intrinsic_type<'tcx>( if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime") && gen_count_ok(own_counts.types, n_tps, "type") - && gen_count_ok(own_counts.consts, 0, "const") + && gen_count_ok(own_counts.consts, n_cts, "const") { let it_def_id = it.owner_id.def_id; check_function_signature( @@ -489,7 +490,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { }; let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic); let sig = ty::Binder::bind_with_vars(sig, bound_vars); - equate_intrinsic_type(tcx, it, n_tps, n_lts, sig) + equate_intrinsic_type(tcx, it, n_tps, n_lts, 0, sig) } /// Type-check `extern "platform-intrinsic" { ... }` functions. @@ -501,9 +502,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) let name = it.ident.name; - let (n_tps, inputs, output) = match name { + let (n_tps, n_cts, inputs, output) = match name { sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => { - (2, vec![param(0), param(0)], param(1)) + (2, 0, vec![param(0), param(0)], param(1)) } sym::simd_add | sym::simd_sub @@ -519,8 +520,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fmax | sym::simd_fpow | sym::simd_saturating_add - | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), - sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)), + | sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)), + sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)), sym::simd_neg | sym::simd_bswap | sym::simd_bitreverse @@ -538,25 +539,25 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_ceil | sym::simd_floor | sym::simd_round - | sym::simd_trunc => (1, vec![param(0)], param(0)), - sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), - sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), - sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), - sym::simd_scatter => (3, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), - sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), - sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)), + | sym::simd_trunc => (1, 0, vec![param(0)], param(0)), + sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)), + sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), + sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), + sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), + sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), + sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), sym::simd_cast | sym::simd_as | sym::simd_cast_ptr | sym::simd_expose_addr - | sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)), - sym::simd_bitmask => (2, vec![param(0)], param(1)), + | sym::simd_from_exposed_addr => (2, 0, vec![param(0)], param(1)), + sym::simd_bitmask => (2, 0, vec![param(0)], param(1)), sym::simd_select | sym::simd_select_bitmask => { - (2, vec![param(0), param(1), param(1)], param(1)) + (2, 0, vec![param(0), param(1), param(1)], param(1)) } - sym::simd_reduce_all | sym::simd_reduce_any => (1, vec![param(0)], tcx.types.bool), + sym::simd_reduce_all | sym::simd_reduce_any => (1, 0, vec![param(0)], tcx.types.bool), sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => { - (2, vec![param(0), param(1)], param(1)) + (2, 0, vec![param(0), param(1)], param(1)) } sym::simd_reduce_add_unordered | sym::simd_reduce_mul_unordered @@ -566,8 +567,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_min | sym::simd_reduce_max | sym::simd_reduce_min_nanless - | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), - sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), + | sym::simd_reduce_max_nanless => (2, 0, vec![param(0)], param(1)), + sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)), + sym::simd_shuffle_generic => (2, 1, vec![param(0), param(0)], param(1)), _ => { let msg = format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, msg).emit(); @@ -577,5 +579,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic); let sig = ty::Binder::dummy(sig); - equate_intrinsic_type(tcx, it, n_tps, 0, sig) + equate_intrinsic_type(tcx, it, n_tps, 0, n_cts, sig) } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 88c98fa979e1c..5fa65f33c763c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -329,41 +329,52 @@ fn bounds_from_generic_predicates<'tcx>( _ => {} } } - let generics = if types.is_empty() { - "".to_string() - } else { - format!( - "<{}>", - types - .keys() - .filter_map(|t| match t.kind() { - ty::Param(_) => Some(t.to_string()), - // Avoid suggesting the following: - // fn foo::Bar>(_: T) where T: Trait, ::Bar: Other {} - _ => None, - }) - .collect::>() - .join(", ") - ) - }; + let mut where_clauses = vec![]; + let mut types_str = vec![]; for (ty, bounds) in types { - where_clauses - .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound)))); - } - for projection in &projections { - let p = projection.skip_binder(); - // FIXME: this is not currently supported syntax, we should be looking at the `types` and - // insert the associated types where they correspond, but for now let's be "lazy" and - // propose this instead of the following valid resugaring: - // `T: Trait, Trait::Assoc = K` → `T: Trait` - where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term)); + if let ty::Param(_) = ty.kind() { + let mut bounds_str = vec![]; + for bound in bounds { + let mut projections_str = vec![]; + for projection in &projections { + let p = projection.skip_binder(); + let alias_ty = p.projection_ty; + if bound == tcx.parent(alias_ty.def_id) && alias_ty.self_ty() == ty { + let name = tcx.item_name(alias_ty.def_id); + projections_str.push(format!("{} = {}", name, p.term)); + } + } + let bound_def_path = tcx.def_path_str(bound); + if projections_str.is_empty() { + where_clauses.push(format!("{}: {}", ty, bound_def_path)); + } else { + bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", "))); + } + } + if bounds_str.is_empty() { + types_str.push(ty.to_string()); + } else { + types_str.push(format!("{}: {}", ty, bounds_str.join(" + "))); + } + } else { + // Avoid suggesting the following: + // fn foo::Bar>(_: T) where T: Trait, ::Bar: Other {} + where_clauses.extend( + bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))), + ); + } } + + let generics = + if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) }; + let where_clauses = if where_clauses.is_empty() { - String::new() + "".to_string() } else { format!(" where {}", where_clauses.join(", ")) }; + (generics, where_clauses) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b7b162ce27bc8..c4fdffb02618a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -24,6 +24,9 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; +use rustc_trait_selection::traits::misc::{ + type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, +}; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ @@ -865,43 +868,65 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { ); }); } else { - let err_ty_str; - let mut is_ptr = true; - - let err = match ty.kind() { + let diag = match ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None, - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => { - is_ptr = false; - err_ty_str = format!("`{ty}`"); - Some(err_ty_str.as_str()) - } + ty::FnPtr(_) => Some(tcx.sess.struct_span_err( + hir_ty.span, + "using function pointers as const generic parameters is forbidden", + )), + ty::RawPtr(_) => Some(tcx.sess.struct_span_err( + hir_ty.span, + "using raw pointers as const generic parameters is forbidden", + )), + _ => Some(tcx.sess.struct_span_err( + hir_ty.span, + format!("`{}` is forbidden as the type of a const generic parameter", ty), + )), }; - if let Some(unsupported_type) = err { - if is_ptr { - tcx.sess.span_err( - hir_ty.span, - format!( - "using {unsupported_type} as const generic parameters is forbidden", - ), - ); - } else { - let mut err = tcx.sess.struct_span_err( - hir_ty.span, - format!( - "{unsupported_type} is forbidden as the type of a const generic parameter", - ), - ); - err.note("the only supported types are integers, `bool` and `char`"); - if tcx.sess.is_nightly_build() { - err.help( - "more complex types are supported with `#![feature(adt_const_params)]`", - ); + if let Some(mut diag) = diag { + diag.note("the only supported types are integers, `bool` and `char`"); + + let cause = ObligationCause::misc(hir_ty.span, param.def_id); + let may_suggest_feature = match type_allowed_to_implement_const_param_ty( + tcx, + tcx.param_env(param.def_id), + ty, + cause, + ) { + // Can never implement `ConstParamTy`, don't suggest anything. + Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false, + // May be able to implement `ConstParamTy`. Only emit the feature help + // if the type is local, since the user may be able to fix the local type. + Err(ConstParamTyImplementationError::InfrigingFields(..)) => { + fn ty_is_local(ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Adt(adt_def, ..) => adt_def.did().is_local(), + // Arrays and slices use the inner type's `ConstParamTy`. + ty::Array(ty, ..) => ty_is_local(*ty), + ty::Slice(ty) => ty_is_local(*ty), + // `&` references use the inner type's `ConstParamTy`. + // `&mut` are not supported. + ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty), + // Say that a tuple is local if any of its components are local. + // This is not strictly correct, but it's likely that the user can fix the local component. + ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)), + _ => false, + } + } + + ty_is_local(ty) } - err.emit(); + // Implments `ConstParamTy`, suggest adding the feature to enable. + Ok(..) => true, + }; + if may_suggest_feature && tcx.sess.is_nightly_build() { + diag.help( + "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types", + ); } + + diag.emit(); } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 94f3e8706fce3..be70acfc35de9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,11 +1,10 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use crate::errors::{ - ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem, -}; +use crate::errors; + use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { let impl_ = tcx.hir().expect_item(impl_did).expect_impl(); - tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span }); + tcx.sess.emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { @@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span); } Err(CopyImplementationError::NotAnAdt) => { - tcx.sess.emit_err(CopyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::CopyImplOnNonAdt { span }); } Err(CopyImplementationError::HasDestructor) => { - tcx.sess.emit_err(CopyImplOnTypeWithDtor { span }); + tcx.sess.emit_err(errors::CopyImplOnTypeWithDtor { span }); } } } @@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span); } Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { - tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span }); + tcx.sess.emit_err(errors::ConstParamTyImplOnNonAdt { span }); } } } @@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let param_env = tcx.param_env(impl_did); - let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg); - let infcx = tcx.infer_ctxt().build(); let cause = ObligationCause::misc(span, impl_did); @@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - create_err(&format!( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{source_path}`, found `{target_path}`", - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynCoercion { + span, + trait_name: "DispatchFromDyn", + note: true, + source_path, + target_path, + }); return; } if def_a.repr().c() || def_a.repr().packed() { - create_err( - "structs implementing `DispatchFromDyn` may not have \ - `#[repr(packed)]` or `#[repr(C)]`", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynRepr { span }); } let fields = &def_a.non_enum_variant().fields; @@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b) { if ok.obligations.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for structs containing the field being coerced, \ - ZST fields with 1 byte alignment, and nothing else", - ) - .note(format!( - "extra field `{}` of type `{}` is not allowed", - field.name, ty_a, - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynZST { + span, + name: field.name, + ty: ty_a, + }); return false; } @@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef .collect::>(); if coerced_fields.is_empty() { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced, none found", - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynSingle { + span, + trait_name: "DispatchFromDyn", + note: true, + }); } else if coerced_fields.len() > 1 { - create_err("implementing the `DispatchFromDyn` trait requires multiple coercions") - .note( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures with a single field \ - being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - coerced_fields.len(), - coerced_fields - .iter() - .map(|field| { - format!( - "`{}` (`{}` to `{}`)", - field.name, - field.ty(tcx, args_a), - field.ty(tcx, args_b), - ) - }) - .collect::>() - .join(", ") - )) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynMulti { + span, + coercions_note: true, + number: coerced_fields.len(), + coercions: coerced_fields + .iter() + .map(|field| { + format!( + "`{}` (`{}` to `{}`)", + field.name, + field.ty(tcx, args_a), + field.ty(tcx, args_b), + ) + }) + .collect::>() + .join(", "), + }); } else { let ocx = ObligationCtxt::new(&infcx); for field in coerced_fields { @@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } } _ => { - create_err( - "the trait `DispatchFromDyn` may only be implemented \ - for a coercion between structures", - ) - .emit(); + tcx.sess.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" }); } } } @@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe if def_a != def_b { let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::DispatchFromDynSame { span, - E0377, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with the same \ - definition; expected `{}`, found `{}`", + trait_name: "CoerceUnsized", + note: true, source_path, - target_path - ) - .emit(); + target_path, + }); return err_info; } @@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe .collect::>(); if diff_fields.is_empty() { - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedOneField { span, - E0374, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures with one field \ - being coerced, none found" - ) - .emit(); + trait_name: "CoerceUnsized", + note: true, + }); return err_info; } else if diff_fields.len() > 1 { let item = tcx.hir().expect_item(impl_did); @@ -463,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe tcx.def_span(impl_did) }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::CoerceUnsizedMulti { span, - E0375, - "implementing the trait \ - `CoerceUnsized` requires multiple \ - coercions" - ) - .note( - "`CoerceUnsized` may only be implemented for \ - a coercion between structures with one field being coerced", - ) - .note(format!( - "currently, {} fields need coercions: {}", - diff_fields.len(), - diff_fields + coercions_note: true, + number: diff_fields.len(), + coercions: diff_fields .iter() - .map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) }) + .map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b)) .collect::>() - .join(", ") - )) - .span_label(span, "requires multiple coercions") - .emit(); + .join(", "), + }); + return err_info; } @@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe } _ => { - struct_span_err!( - tcx.sess, - span, - E0376, - "the trait `CoerceUnsized` may only be implemented \ - for a coercion between structures" - ) - .emit(); + tcx.sess.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" }); return err_info; } }; @@ -540,13 +491,6 @@ fn infringing_fields_error( let trait_name = tcx.def_path_str(trait_did); - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0204, - "the trait `{trait_name}` cannot be implemented for this type" - ); - // We'll try to suggest constraining type parameters to fulfill the requirements of // their `Copy` implementation. let mut errors: BTreeMap<_, Vec<_>> = Default::default(); @@ -554,14 +498,15 @@ fn infringing_fields_error( let mut seen_tys = FxHashSet::default(); + let mut label_spans = Vec::new(); + for (field, ty, reason) in fields { // Only report an error once per type. if !seen_tys.insert(ty) { continue; } - let field_span = tcx.def_span(field.did); - err.span_label(field_span, format!("this field does not implement `{trait_name}`")); + label_spans.push(tcx.def_span(field.did)); match reason { InfringingFieldsReason::Fulfill(fulfillment_errors) => { @@ -625,13 +570,24 @@ fn infringing_fields_error( } } } + let mut notes = Vec::new(); for ((ty, error_predicate), spans) in errors { let span: MultiSpan = spans.into(); - err.span_note( + notes.push(errors::ImplForTyRequires { span, - format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"), - ); + error_predicate, + trait_name: trait_name.clone(), + ty, + }); } + + let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy { + span: impl_span, + trait_name, + label_spans, + notes, + }); + suggest_constraining_type_params( tcx, tcx.hir().get_generics(impl_did).expect("impls always have generics"), diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index cd37221ae6f80..221df4e36b296 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1374,7 +1374,7 @@ fn impl_trait_ref( // make astconv happy. let mut path_segments = ast_trait_ref.path.segments.to_vec(); let last_segment = path_segments.len() - 1; - let mut args = path_segments[last_segment].args().clone(); + let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host))); args.args = &args.args[..args.args.len() - 1]; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4705e40988b2f..0efe82b20eebf 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -963,6 +963,25 @@ pub struct InherentTyOutside { pub span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct DispatchFromDynCoercion<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_same_note)] + pub note: bool, + pub source_path: String, + pub target_path: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_repr, code = "E0378")] +pub struct DispatchFromDynRepr { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = "E0390")] #[help] @@ -1025,3 +1044,108 @@ pub struct InherentNominal { #[label] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_zst, code = "E0378")] +#[note] +pub struct DispatchFromDynZST<'a> { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct DispatchFromDynSingle<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_single_note)] + pub note: bool, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_dispatch_from_dyn_multi, code = "E0378")] +#[note] +pub struct DispatchFromDynMulti { + #[primary_span] + pub span: Span, + #[note(hir_analysis_coercions_note)] + pub coercions_note: bool, + pub number: usize, + pub coercions: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0376")] +pub struct DispatchFromDynStruct<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0377")] +pub struct DispatchFromDynSame<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_same_note)] + pub note: bool, + pub source_path: String, + pub target_path: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0374")] +pub struct CoerceUnsizedOneField<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, + #[note(hir_analysis_coercion_between_struct_single_note)] + pub note: bool, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_multi, code = "E0375")] +#[note] +pub struct CoerceUnsizedMulti { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_coercions_note)] + pub coercions_note: bool, + pub number: usize, + pub coercions: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_unsized_may, code = "E0378")] +pub struct CoerceUnsizedMay<'a> { + #[primary_span] + pub span: Span, + pub trait_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_trait_cannot_impl_for_ty, code = "E0204")] +pub struct TraitCannotImplForTy { + #[primary_span] + pub span: Span, + pub trait_name: String, + #[label] + pub label_spans: Vec, + #[subdiagnostic] + pub notes: Vec, +} + +#[derive(Subdiagnostic)] +#[note(hir_analysis_requires_note)] +pub struct ImplForTyRequires { + #[primary_span] + pub span: MultiSpan, + pub error_predicate: String, + pub trait_name: String, + pub ty: String, +} diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 256a4bf944910..d97691369c958 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -644,7 +644,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.can_eq(self.param_env, ty, expected) { err.span_label( ex.span, - format!("expected because of this `break`"), + "expected because of this `break`", ); exit = true; } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index b34900da83bb2..5c3beee284fca 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -621,7 +621,7 @@ fn foo(&self) -> Self::T { String::new() } { diag.span_label( item.span, - format!("associated type is `default` and may be overridden"), + "associated type is `default` and may be overridden", ); return true; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 460d54739a2e5..3c5cde4309b44 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1316,6 +1316,40 @@ impl<'tcx> LateContext<'tcx> { }) } + /// 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). + /// Type-check adjustments are not taken in account in this function. + /// + /// Examples: + /// ``` + /// let abc = 1; + /// let def = abc + 2; + /// // ^^^^^^^ output + /// let def = def; + /// dbg!(def); + /// // ^^^ input + /// ``` + pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> { + expr = expr.peel_blocks(); + + while let hir::ExprKind::Path(ref qpath) = expr.kind + && let Some(parent_node) = match self.qpath_res(qpath, expr.hir_id) { + Res::Local(hir_id) => self.tcx.hir().find_parent(hir_id), + _ => None, + } + && let Some(init) = match parent_node { + hir::Node::Expr(expr) => Some(expr), + hir::Node::Local(hir::Local { init, .. }) => *init, + _ => None + } + { + expr = init.peel_blocks(); + } + expr + } + /// If the given expression is a local binding, find the initializer expression. /// If that initializer expression is another local or **outside** (`const`/`static`) /// binding, find its initializer again. @@ -1338,7 +1372,10 @@ impl<'tcx> LateContext<'tcx> { /// dbg!(def); /// // ^^^ input /// ``` - pub fn expr_or_init<'a>(&self, mut expr: &'a hir::Expr<'tcx>) -> &'a hir::Expr<'tcx> { + pub fn expr_or_init_with_outside_body<'a>( + &self, + mut expr: &'a hir::Expr<'tcx>, + ) -> &'a hir::Expr<'tcx> { expr = expr.peel_blocks(); while let hir::ExprKind::Path(ref qpath) = expr.kind diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 7b291d558e03b..e1df69bdaf252 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -5,19 +5,18 @@ use rustc_hir::def::DefKind; use rustc_middle::query::Providers; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_session::lint::{lint_array, LintArray}; use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::FIRST_VARIANT; use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub}; -use crate::types; +use crate::{types, LintVec}; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { clashing_extern_declarations, ..*providers }; } -pub(crate) fn get_lints() -> LintArray { - lint_array!(CLASHING_EXTERN_DECLARATIONS) +pub(crate) fn get_lints() -> LintVec { + vec![CLASHING_EXTERN_DECLARATIONS] } fn clashing_extern_declarations(tcx: TyCtxt<'_>, (): ()) { diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index 1841e7c85a817..e398059ade9fc 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -84,9 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 { ) }; - let mut init = cx.expr_or_init(arg); + let mut init = cx.expr_or_init_with_outside_body(arg); while let ExprKind::AddrOf(.., inner) = init.kind { - init = cx.expr_or_init(inner); + init = cx.expr_or_init_with_outside_body(inner); } match init.kind { ExprKind::Lit(Spanned { node: lit, .. }) => { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 284560465d630..72c103f2d4a1e 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -130,7 +130,7 @@ pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId}; -pub use rustc_session::lint::{LintArray, LintPass}; +pub use rustc_session::lint::{LintPass, LintVec}; fluent_messages! { "../messages.ftl" } @@ -196,7 +196,7 @@ late_lint_methods!( BoxPointers: BoxPointers, PathStatements: PathStatements, LetUnderscore: LetUnderscore, - InvalidReferenceCasting: InvalidReferenceCasting::default(), + InvalidReferenceCasting: InvalidReferenceCasting, // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, NonUpperCaseGlobals: NonUpperCaseGlobals, diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index bc0b9d6d81871..cfbca6efbfa54 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -98,6 +98,12 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, cx.param_env, did, args) else { return }; // (Re)check that it implements the noop diagnostic. let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; + if !matches!( + name, + sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref + ) { + return; + } let receiver_ty = cx.typeck_results().expr_ty(receiver); let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 7d2a910264049..508f3e1ec3106 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -111,7 +111,7 @@ macro_rules! declare_combined_late_lint_pass { } } - $v fn get_lints() -> $crate::LintArray { + $v fn get_lints() -> $crate::LintVec { let mut lints = Vec::new(); $(lints.extend_from_slice(&$pass::get_lints());)* lints @@ -226,7 +226,7 @@ macro_rules! declare_combined_early_lint_pass { } } - $v fn get_lints() -> $crate::LintArray { + $v fn get_lints() -> $crate::LintVec { let mut lints = Vec::new(); $(lints.extend_from_slice(&$pass::get_lints());)* lints diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d540f473ae8f1..39def599be8d8 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -1,8 +1,7 @@ use rustc_ast::Mutability; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, QPath, StmtKind, UnOp}; +use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_middle::ty::{self, TypeAndMut}; -use rustc_span::{sym, Span}; +use rustc_span::sym; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; @@ -34,38 +33,18 @@ declare_lint! { "casts of `&T` to `&mut T` without interior mutability" } -#[derive(Default)] -pub struct InvalidReferenceCasting { - casted: FxHashMap, -} - -impl_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); +declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { - fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) { - let StmtKind::Local(local) = stmt.kind else { - return; - }; - let Local { init: Some(init), els: None, .. } = local else { - return; - }; - - if is_cast_from_const_to_mut(cx, init) { - self.casted.insert(local.pat.hir_id, init.span); - } - } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else { return; }; - let orig_cast = if is_cast_from_const_to_mut(cx, e) { - None - } else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind - && let Res::Local(hir_id) = &path.res - && let Some(orig_cast) = self.casted.get(hir_id) { - Some(*orig_cast) + let init = cx.expr_or_init(e); + + let orig_cast = if is_cast_from_const_to_mut(cx, init) { + if init.span != e.span { Some(init.span) } else { None } } else { return; }; @@ -125,99 +104,51 @@ fn is_operation_we_care_about<'tcx>( deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e)) } -fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { - let e = e.peel_blocks(); +fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, orig_expr: &'tcx Expr<'tcx>) -> bool { + let mut need_check_freeze = false; + let mut e = orig_expr; - fn from_casts<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'tcx>, - need_check_freeze: &mut bool, - ) -> Option<&'tcx Expr<'tcx>> { - // as *mut ... - let mut e = if let ExprKind::Cast(e, t) = e.kind - && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { - e - // .cast_mut() + let end_ty = cx.typeck_results().node_type(orig_expr.hir_id); + + // Bail out early if the end type is **not** a mutable pointer. + if !matches!(end_ty.kind(), ty::RawPtr(TypeAndMut { ty: _, mutbl: Mutability::Mut })) { + return false; + } + + loop { + e = e.peel_blocks(); + // as ... + e = if let ExprKind::Cast(expr, _) = e.kind { + expr + // .cast(), .cast_mut() or .cast_const() } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) + ) + { expr - // UnsafeCell::raw_get() + // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() } else if let ExprKind::Call(path, [arg]) = e.kind && let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) + ) { - *need_check_freeze = true; + if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { + need_check_freeze = true; + } arg } else { - return None; + break; }; - - let mut had_at_least_one_cast = false; - loop { - e = e.peel_blocks(); - // as *mut/const ... or as - e = if let ExprKind::Cast(expr, t) = e.kind - && matches!(cx.typeck_results().node_type(t.hir_id).kind(), ty::RawPtr(_) | ty::Uint(_)) { - had_at_least_one_cast = true; - expr - // .cast(), .cast_mut() or .cast_const() - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) - ) - { - had_at_least_one_cast = true; - expr - // ptr::from_ref() or UnsafeCell::raw_get() - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get) - ) - { - if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { - *need_check_freeze = true; - } - return Some(arg); - } else if had_at_least_one_cast { - return Some(e); - } else { - return None; - }; - } - } - - fn from_transmute<'tcx>( - cx: &LateContext<'tcx>, - e: &'tcx Expr<'tcx>, - ) -> Option<&'tcx Expr<'tcx>> { - // mem::transmute::<_, *mut _>() - if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::transmute, def_id) - && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(e.hir_id).kind() { - Some(arg) - } else { - None - } } - let mut need_check_freeze = false; - let Some(e) = from_casts(cx, e, &mut need_check_freeze).or_else(|| from_transmute(cx, e)) - else { - return false; - }; - - let e = e.peel_blocks(); - let node_type = cx.typeck_results().node_type(e.hir_id); - if let ty::Ref(_, inner_ty, Mutability::Not) = node_type.kind() { + let start_ty = cx.typeck_results().node_type(e.hir_id); + if let ty::Ref(_, inner_ty, Mutability::Not) = start_ty.kind() { // If an UnsafeCell method is involved we need to additionaly check the // inner type for the presence of the Freeze trait (ie does NOT contain // an UnsafeCell), since in that case we would incorrectly lint on valid casts. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 84e7ecb0b881c..7ba589c3b5a39 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -785,16 +785,7 @@ macro_rules! declare_tool_lint { ); } -/// Declares a static `LintArray` and return it as an expression. -#[macro_export] -macro_rules! lint_array { - ($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) }; - ($( $lint:expr ),*) => {{ - vec![$($lint),*] - }} -} - -pub type LintArray = Vec<&'static Lint>; +pub type LintVec = Vec<&'static Lint>; pub trait LintPass { fn name(&self) -> &'static str; @@ -808,7 +799,7 @@ macro_rules! impl_lint_pass { fn name(&self) -> &'static str { stringify!($ty) } } impl $ty { - pub fn get_lints() -> $crate::LintArray { $crate::lint_array!($($lint),*) } + pub fn get_lints() -> $crate::LintVec { vec![$($lint),*] } } }; } diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index cd770c395e4d3..3ecd5b9cd3456 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -63,11 +63,14 @@ impl<'tcx> BasicBlocks<'tcx> { } /// Returns basic blocks in a reverse postorder. + /// + /// See [`traversal::reverse_postorder`]'s docs to learn what is preorder traversal. + /// + /// [`traversal::reverse_postorder`]: crate::mir::traversal::reverse_postorder #[inline] pub fn reverse_postorder(&self) -> &[BasicBlock] { self.cache.reverse_postorder.get_or_init(|| { - let mut rpo: Vec<_> = - Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect(); + let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect(); rpo.reverse(); rpo }) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 349b32c10fb9e..76567c3f6b0a0 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1146,10 +1146,10 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => { write!(fmt, "[-{offset:?} of {min_length:?}]")?; } - ProjectionElem::Subslice { from, to, from_end: true } if to == 0 => { + ProjectionElem::Subslice { from, to: 0, from_end: true } => { write!(fmt, "[{from:?}:]")?; } - ProjectionElem::Subslice { from, to, from_end: true } if from == 0 => { + ProjectionElem::Subslice { from: 0, to, from_end: true } => { write!(fmt, "[:-{to:?}]")?; } ProjectionElem::Subslice { from, to, from_end: true } => { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 201926fee3e02..55f895f73b48b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -139,6 +139,7 @@ pub enum RuntimePhase { /// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::GeneratorDrop`] /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` + /// * [`PlaceElem::OpaqueCast`] /// /// And the following variants are allowed: /// * [`StatementKind::Retag`] diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index ec16a8470c412..a1ff8410eac4a 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -41,6 +41,12 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { } } +/// Preorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that +/// returns basic blocks in a preorder. +/// +/// See [`Preorder`]'s docs to learn what is preorder traversal. pub fn preorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Preorder<'a, 'tcx> { Preorder::new(body, START_BLOCK) } @@ -178,7 +184,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but // since we've already visited `E`, that child isn't added to the stack. The last // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A] - while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next_back() { + while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) { if self.visited.insert(bb) { if let Some(term) = &self.basic_blocks[bb].terminator { self.visit_stack.push((bb, term.successors())); @@ -188,16 +194,14 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { } } -impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); +impl<'tcx> Iterator for Postorder<'_, 'tcx> { + type Item = BasicBlock; - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - let next = self.visit_stack.pop(); - if next.is_some() { - self.traverse_successor(); - } + fn next(&mut self) -> Option { + let (bb, _) = self.visit_stack.pop()?; + self.traverse_successor(); - next.map(|(bb, _)| (bb, &self.basic_blocks[bb])) + Some(bb) } fn size_hint(&self) -> (usize, Option) { @@ -215,10 +219,14 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { } } -/// Creates an iterator over the `Body`'s basic blocks, that: +/// Postorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that: /// - returns basic blocks in a postorder, /// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the /// postorder itself. +/// +/// See [`Postorder`]'s docs to learn what is postorder traversal. pub fn postorder<'a, 'tcx>( body: &'a Body<'tcx>, ) -> impl Iterator)> + ExactSizeIterator + DoubleEndedIterator @@ -226,7 +234,28 @@ pub fn postorder<'a, 'tcx>( reverse_postorder(body).rev() } -/// Reverse postorder traversal of a graph +/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular +/// order. +/// +/// This is clearer than writing `preorder` in cases where the order doesn't matter. +pub fn reachable<'a, 'tcx>( + body: &'a Body<'tcx>, +) -> impl 'a + Iterator)> { + preorder(body) +} + +/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. +pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet { + let mut iter = preorder(body); + iter.by_ref().for_each(drop); + iter.visited +} + +/// Reverse postorder traversal of a graph. +/// +/// This function creates an iterator over the `Body`'s basic blocks, that: +/// - returns basic blocks in a reverse postorder, +/// - makes use of the `BasicBlocks` CFG cache's reverse postorder. /// /// Reverse postorder is the reverse order of a postorder traversal. /// This is different to a preorder traversal and represents a natural @@ -246,65 +275,6 @@ pub fn postorder<'a, 'tcx>( /// A reverse postorder traversal of this graph is either `A B C D` or `A C B D` /// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to /// a topological sort. -/// -/// Construction of a `ReversePostorder` traversal requires doing a full -/// postorder traversal of the graph, therefore this traversal should be -/// constructed as few times as possible. Use the `reset` method to be able -/// to re-use the traversal -#[derive(Clone)] -pub struct ReversePostorder<'a, 'tcx> { - body: &'a Body<'tcx>, - blocks: Vec, - idx: usize, -} - -impl<'a, 'tcx> ReversePostorder<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> { - let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect(); - let len = blocks.len(); - ReversePostorder { body, blocks, idx: len } - } -} - -impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> { - type Item = (BasicBlock, &'a BasicBlockData<'tcx>); - - fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> { - if self.idx == 0 { - return None; - } - self.idx -= 1; - - self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb])) - } - - fn size_hint(&self) -> (usize, Option) { - (self.idx, Some(self.idx)) - } -} - -impl<'a, 'tcx> ExactSizeIterator for ReversePostorder<'a, 'tcx> {} - -/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular -/// order. -/// -/// This is clearer than writing `preorder` in cases where the order doesn't matter. -pub fn reachable<'a, 'tcx>( - body: &'a Body<'tcx>, -) -> impl 'a + Iterator)> { - preorder(body) -} - -/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. -pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet { - let mut iter = preorder(body); - (&mut iter).for_each(drop); - iter.visited -} - -/// Creates an iterator over the `Body`'s basic blocks, that: -/// - returns basic blocks in a reverse postorder, -/// - makes use of the `BasicBlocks` CFG cache's reverse postorder. pub fn reverse_postorder<'a, 'tcx>( body: &'a Body<'tcx>, ) -> impl Iterator)> + ExactSizeIterator + DoubleEndedIterator diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 95dced644e161..d440ca319260c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -740,9 +740,7 @@ fn non_exhaustive_match<'p, 'tcx>( )); } } else if ty == cx.tcx.types.str_ { - err.note(format!( - "`&str` cannot be matched exhaustively, so a wildcard `_` is necessary", - )); + err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary"); } else if cx.is_foreign_non_exhaustive_enum(ty) { err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively")); } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index e24685cb90f73..c9991e499b32a 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -194,6 +194,7 @@ where D: DropElaborator<'b, 'tcx>, 'tcx: 'b, { + #[instrument(level = "trace", skip(self), ret)] fn place_ty(&self, place: Place<'tcx>) -> Ty<'tcx> { place.ty(self.elaborator.body(), self.tcx()).ty } @@ -220,11 +221,9 @@ where // // FIXME: I think we should just control the flags externally, // and then we do not need this machinery. + #[instrument(level = "debug")] pub fn elaborate_drop(&mut self, bb: BasicBlock) { - debug!("elaborate_drop({:?}, {:?})", bb, self); - let style = self.elaborator.drop_style(self.path, DropFlagMode::Deep); - debug!("elaborate_drop({:?}, {:?}): live - {:?}", bb, self, style); - match style { + match self.elaborator.drop_style(self.path, DropFlagMode::Deep) { DropStyle::Dead => { self.elaborator .patch() diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 5b24fa10beae8..767f8e9f4fa15 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -763,7 +763,7 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option // and `_1` is the `Place` for `somenum`. // // If and when the Issue is resolved, remove this special case match pattern: - StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None, + StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None, // Retain spans from all other statements StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 6a89d06727576..b62d7da2a4cca 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -170,6 +170,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { self.ctxt.param_env() } + #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false), diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 4eee45f8d000b..886ff760481e0 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -54,11 +54,8 @@ impl EnumSizeOpt { let layout = tcx.layout_of(param_env.and(ty)).ok()?; let variants = match &layout.variants { Variants::Single { .. } => return None, - Variants::Multiple { tag_encoding, .. } - if matches!(tag_encoding, TagEncoding::Niche { .. }) => - { - return None; - } + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None, + Variants::Multiple { variants, .. } if variants.len() <= 1 => return None, Variants::Multiple { variants, .. } => variants, }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9e4bc456d51a2..754f2ee837682 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -480,6 +480,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ // These next passes must be executed together &add_call_guards::CriticalCallEdges, + &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too. &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer // necessary as well as well as forcing any call in a non-unwinding @@ -526,7 +527,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { body, &[ &check_alignment::CheckAlignment, - &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 065793348e4c3..55f1eac6f8468 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -8,16 +8,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; impl<'tcx> MirPass<'tcx> for RevealAll { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 3 || super::inline::Inline.is_enabled(sess) - } - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // Do not apply this transformation to generators. - if body.generator.is_some() { - return; - } - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body); } @@ -34,6 +25,29 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { self.tcx } + #[inline] + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + _context: PlaceContext, + _location: Location, + ) { + // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. + if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { + return; + } + // `OpaqueCast` projections are only needed if there are opaque types on which projections are performed. + // After the `RevealAll` pass, all opaque types are replaced with their hidden types, so we don't need these + // projections anymore. + place.projection = self.tcx.mk_place_elems( + &place + .projection + .into_iter() + .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) + .collect::>(), + ); + } + #[inline] fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _: Location) { // We have to use `try_normalize_erasing_regions` here, since it's diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 3a675752fba91..af9514ed6bb5b 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -78,14 +78,10 @@ impl SsaLocals { visitor.assignments[local] = Set1::One(LocationExtended::Arg); } - if body.basic_blocks.len() > 2 { - for (bb, data) in traversal::reverse_postorder(body) { - visitor.visit_basic_block_data(bb, data); - } - } else { - for (bb, data) in body.basic_blocks.iter_enumerated() { - visitor.visit_basic_block_data(bb, data); - } + // For SSA assignments, a RPO visit will see the assignment before it sees any use. + // We only visit reachable nodes: computing `dominates` on an unreachable node ICEs. + for (bb, data) in traversal::reverse_postorder(body) { + visitor.visit_basic_block_data(bb, data); } for var_debug_info in &body.var_debug_info { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 2c4bc7bb5687f..05b6c40620651 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -509,7 +509,7 @@ parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of parse_maybe_recover_from_bad_qpath_stage_2 = missing angle brackets in associated item path - .suggestion = try: `{$ty}` + .suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths parse_maybe_recover_from_bad_type_plus = expected a path on the left-hand side of `+`, not `{$ty}` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 5d3ec68355203..7c75e440aaabd 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -59,9 +59,18 @@ pub(crate) enum BadTypePlusSub { #[diag(parse_maybe_recover_from_bad_qpath_stage_2)] pub(crate) struct BadQPathStage2 { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, - pub ty: String, + #[subdiagnostic] + pub wrap: WrapType, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct WrapType { + #[suggestion_part(code = "<")] + pub lo: Span, + #[suggestion_part(code = ">")] + pub hi: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 6c8ef34063f87..06b1b1523edbd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -16,7 +16,7 @@ use crate::errors::{ StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, - UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, + UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::fluent_generated as fluent; @@ -1589,10 +1589,9 @@ impl<'a> Parser<'a> { self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; path.span = ty_span.to(self.prev_token.span); - let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty)); self.sess.emit_err(BadQPathStage2 { - span: path.span, - ty: format!("<{}>::{}", ty_str, pprust::path_to_string(&path)), + span: ty_span, + wrap: WrapType { lo: ty_span.shrink_to_lo(), hi: ty_span.shrink_to_hi() }, }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c3c43346ed828..15ec727e4c99a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4140,6 +4140,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); } + fn resolve_expr_field(&mut self, f: &'ast ExprField, e: &'ast Expr) { + self.resolve_expr(&f.expr, Some(e)); + self.visit_ident(f.ident); + walk_list!(self, visit_attribute, f.attrs.iter()); + } + fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -4155,7 +4161,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ExprKind::Struct(ref se) => { self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct); - visit::walk_expr(self, expr); + // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the + // parent in for accurate suggestions when encountering `Foo { bar }` that should + // have been `Foo { bar: self.bar }`. + if let Some(qself) = &se.qself { + self.visit_ty(&qself.ty); + } + self.visit_path(&se.path, expr.id); + walk_list!(self, resolve_expr_field, &se.fields, expr); + match &se.rest { + StructRest::Base(expr) => self.visit_expr(expr), + StructRest::Rest(_span) => {} + StructRest::None => {} + } } ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 64440a6c04e7a..bc5f8a37b0ff4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -41,7 +41,7 @@ type Res = def::Res; /// A field or associated item from self type suggested in case of resolution failure. enum AssocSuggestion { - Field, + Field(Span), MethodWithSelf { called: bool }, AssocFn { called: bool }, AssocType, @@ -51,7 +51,7 @@ enum AssocSuggestion { impl AssocSuggestion { fn action(&self) -> &'static str { match self { - AssocSuggestion::Field => "use the available field", + AssocSuggestion::Field(_) => "use the available field", AssocSuggestion::MethodWithSelf { called: true } => { "call the method with the fully-qualified path" } @@ -186,7 +186,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fallback_label: format!("not a {expected}"), span, span_label: match res { - Res::Def(kind, def_id) if kind == DefKind::TyParam => { + Res::Def(DefKind::TyParam, def_id) => { Some((self.r.def_span(def_id), "found this type parameter")) } _ => None, @@ -215,7 +215,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } else { let mut span_label = None; - let item_span = path.last().unwrap().ident.span; + let item_ident = path.last().unwrap().ident; + let item_span = item_ident.span; let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 { debug!(?self.diagnostic_metadata.current_impl_items); debug!(?self.diagnostic_metadata.current_function); @@ -231,9 +232,35 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { }) { let sp = item_span.shrink_to_lo(); + + // Account for `Foo { field }` when suggesting `self.field` so we result on + // `Foo { field: self.field }`. + let field = match source { + PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. })) => { + expr.fields.iter().find(|f| f.ident == item_ident) + } + _ => None, + }; + let pre = if let Some(field) = field && field.is_shorthand { + format!("{item_ident}: ") + } else { + String::new() + }; + // Ensure we provide a structured suggestion for an assoc fn only for + // expressions that are actually a fn call. + let is_call = match field { + Some(ast::ExprField { expr, .. }) => { + matches!(expr.kind, ExprKind::Call(..)) + } + _ => matches!( + source, + PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), ..})), + ), + }; + match &item.kind { AssocItemKind::Fn(fn_) - if !sig.decl.has_self() && fn_.sig.decl.has_self() => { + if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() => { // Ensure that we only suggest `self.` if `self` is available, // you can't call `fn foo(&self)` from `fn bar()` (#115992). // We also want to mention that the method exists. @@ -243,20 +270,28 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { )); None } + AssocItemKind::Fn(fn_) + if !fn_.sig.decl.has_self() && !is_call => { + span_label = Some(( + item.ident.span, + "an associated function by that name is available on `Self` here", + )); + None + } AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => Some(( sp, "consider using the method on `Self`", - "self.".to_string(), + format!("{pre}self."), )), AssocItemKind::Fn(_) => Some(( sp, "consider using the associated function on `Self`", - "Self::".to_string(), + format!("{pre}Self::"), )), AssocItemKind::Const(..) => Some(( sp, "consider using the associated constant on `Self`", - "Self::".to_string(), + format!("{pre}Self::"), )), _ => None } @@ -621,17 +656,30 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) { let self_is_available = self.self_value_is_available(path[0].ident.span); + // Account for `Foo { field }` when suggesting `self.field` so we result on + // `Foo { field: self.field }`. + let pre = match source { + PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. })) + if expr + .fields + .iter() + .any(|f| f.ident == path[0].ident && f.is_shorthand) => + { + format!("{path_str}: ") + } + _ => String::new(), + }; match candidate { - AssocSuggestion::Field => { + AssocSuggestion::Field(field_span) => { if self_is_available { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), "you might have meant to use the available field", - format!("self.{path_str}"), + format!("{pre}self."), Applicability::MachineApplicable, ); } else { - err.span_label(span, "a field by this name exists in `Self`"); + err.span_label(field_span, "a field by that name exists in `Self`"); } } AssocSuggestion::MethodWithSelf { called } if self_is_available => { @@ -640,10 +688,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } else { "you might have meant to refer to the method" }; - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), msg, - format!("self.{path_str}"), + "self.".to_string(), Applicability::MachineApplicable, ); } @@ -651,10 +699,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | AssocSuggestion::AssocFn { .. } | AssocSuggestion::AssocConst | AssocSuggestion::AssocType => { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.shrink_to_lo(), format!("you might have meant to {}", candidate.action()), - format!("Self::{path_str}"), + "Self::".to_string(), Applicability::MachineApplicable, ); } @@ -1667,11 +1715,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { resolution.full_res() { if let Some(field_ids) = self.r.field_def_ids(did) { - if field_ids + if let Some(field_id) = field_ids .iter() - .any(|&field_id| ident.name == self.r.tcx.item_name(field_id)) + .find(|&&field_id| ident.name == self.r.tcx.item_name(field_id)) { - return Some(AssocSuggestion::Field); + return Some(AssocSuggestion::Field(self.r.def_span(*field_id))); } } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 441aafd1257ba..1a9dea99f643f 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -86,6 +86,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::ImplDef(self.create_def_id(did)) } + pub fn region_def(&mut self, did: DefId) -> stable_mir::ty::RegionDef { + stable_mir::ty::RegionDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 5ff17613b4e56..c6c97ce35e8b9 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,7 +7,8 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. -use hir::def::DefKind; +use crate::rustc_smir::hir::def::DefKind; +use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region}; use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; @@ -1500,9 +1501,39 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity { impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { type T = stable_mir::ty::Region; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - // FIXME: add a real implementation of stable regions - opaque(self) + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + Region { kind: self.kind().stable(tables) } + } +} + +impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { + type T = stable_mir::ty::RegionKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::RegionKind; + match self { + ty::ReEarlyBound(early_reg) => RegionKind::ReEarlyBound(EarlyBoundRegion { + def_id: tables.region_def(early_reg.def_id), + index: early_reg.index, + name: early_reg.name.to_string(), + }), + ty::ReLateBound(db_index, bound_reg) => RegionKind::ReLateBound( + db_index.as_u32(), + BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) }, + ), + ty::ReStatic => RegionKind::ReStatic, + ty::RePlaceholder(place_holder) => { + RegionKind::RePlaceholder(stable_mir::ty::Placeholder { + universe: place_holder.universe.as_u32(), + bound: BoundRegion { + var: place_holder.bound.var.as_u32(), + kind: place_holder.bound.kind.stable(tables), + }, + }) + } + ty::ReErased => RegionKind::ReErased, + _ => unreachable!("{self:?}"), + } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index c58fdbcb5e1b6..772e09291a139 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1753,7 +1753,7 @@ impl SourceFile { // is recorded. let diff = match self.normalized_pos.binary_search_by(|np| np.pos.cmp(&pos)) { Ok(i) => self.normalized_pos[i].diff, - Err(i) if i == 0 => 0, + Err(0) => 0, Err(i) => self.normalized_pos[i - 1].diff, }; @@ -1775,7 +1775,7 @@ impl SourceFile { .binary_search_by(|np| (np.pos.0 + np.diff).cmp(&(self.start_pos.0 + offset))) { Ok(i) => self.normalized_pos[i].diff, - Err(i) if i == 0 => 0, + Err(0) => 0, Err(i) => self.normalized_pos[i - 1].diff, }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 382754be2ca83..4f46256626f5e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1465,6 +1465,7 @@ symbols! { simd_shl, simd_shr, simd_shuffle, + simd_shuffle_generic, simd_sub, simd_trunc, simd_xor, diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs deleted file mode 100644 index be48447e27c24..0000000000000 --- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! This module both handles the global cache which stores "finished" goals, -//! and the provisional cache which contains partially computed goals. -//! -//! The provisional cache is necessary when dealing with coinductive cycles. -//! -//! For more information about the provisional cache and coinduction in general, -//! check out the relevant section of the rustc-dev-guide. -//! -//! FIXME(@lcnr): Write that section, feel free to ping me if you need help here -//! before then or if I still haven't done that before January 2023. -use super::StackDepth; -use rustc_data_structures::fx::FxHashMap; -use rustc_index::IndexVec; -use rustc_middle::traits::solve::{CanonicalInput, QueryResult}; - -rustc_index::newtype_index! { - pub struct EntryIndex {} -} - -#[derive(Debug, Clone)] -pub(super) struct ProvisionalEntry<'tcx> { - /// In case we have a coinductive cycle, this is the - /// the current provisional result of this goal. - /// - /// This starts out as `None` for all goals and gets to some - /// when the goal gets popped from the stack or we rerun evaluation - /// for this goal to reach a fixpoint. - pub(super) response: Option>, - /// In case of a cycle, the position of deepest stack entry involved - /// in that cycle. This is monotonically decreasing in the stack as all - /// elements between the current stack element in the deepest stack entry - /// involved have to also be involved in that cycle. - /// - /// We can only move entries to the global cache once we're complete done - /// with the cycle. If this entry has not been involved in a cycle, - /// this is just its own depth. - pub(super) depth: StackDepth, - - /// The goal for this entry. Should always be equal to the corresponding goal - /// in the lookup table. - pub(super) input: CanonicalInput<'tcx>, -} - -pub(super) struct ProvisionalCache<'tcx> { - pub(super) entries: IndexVec>, - // FIXME: This is only used to quickly check whether a given goal - // is in the cache. We should experiment with using something like - // `SsoHashSet` here because in most cases there are only a few entries. - pub(super) lookup_table: FxHashMap, EntryIndex>, -} - -impl<'tcx> ProvisionalCache<'tcx> { - pub(super) fn empty() -> ProvisionalCache<'tcx> { - ProvisionalCache { entries: Default::default(), lookup_table: Default::default() } - } - - pub(super) fn is_empty(&self) -> bool { - self.entries.is_empty() && self.lookup_table.is_empty() - } - - /// Adds a dependency from the current leaf to `target` in the cache - /// to prevent us from moving any goals which depend on the current leaf - /// to the global cache while we're still computing `target`. - /// - /// Its important to note that `target` may already be part of a different cycle. - /// In this case we have to ensure that we also depend on all other goals - /// in the existing cycle in addition to the potentially direct cycle with `target`. - pub(super) fn add_dependency_of_leaf_on(&mut self, target: EntryIndex) { - let depth = self.entries[target].depth; - for provisional_entry in &mut self.entries.raw[target.index()..] { - // The depth of `target` is the position of the deepest goal in the stack - // on which `target` depends. That goal is the `root` of this cycle. - // - // Any entry which was added after `target` is either on the stack itself - // at which point its depth is definitely at least as high as the depth of - // `root`. If it's not on the stack itself it has to depend on a goal - // between `root` and `leaf`. If it were to depend on a goal deeper in the - // stack than `root`, then `root` would also depend on that goal, at which - // point `root` wouldn't be the root anymore. - debug_assert!(provisional_entry.depth >= depth); - provisional_entry.depth = depth; - } - - // We only update entries which were added after `target` as no other - // entry should have a higher depth. - // - // Any entry which previously had a higher depth than target has to - // be between `target` and `root`. Because of this we would have updated - // its depth when calling `add_dependency_of_leaf_on(root)` for `target`. - if cfg!(debug_assertions) { - self.entries.iter().all(|e| e.depth <= depth); - } - } - - pub(super) fn depth(&self, entry_index: EntryIndex) -> StackDepth { - self.entries[entry_index].depth - } - - pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> Option> { - self.entries[entry_index].response - } -} diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 728d0fc1ae763..33513f6bd439d 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -1,10 +1,7 @@ -mod cache; - -use self::cache::ProvisionalEntry; use super::inspect; use super::inspect::ProofTreeBuilder; use super::SolverMode; -use cache::ProvisionalCache; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_index::Idx; use rustc_index::IndexVec; @@ -27,8 +24,14 @@ struct StackEntry<'tcx> { // The maximum depth reached by this stack entry, only up-to date // for the top of the stack and lazily updated for the rest. reached_depth: StackDepth, + // In case of a cycle, the depth of the root. + cycle_root_depth: StackDepth, + encountered_overflow: bool, has_been_used: bool, + /// Starts out as `None` and gets set when rerunning this + /// goal in case we encounter a cycle. + provisional_result: Option>, /// We put only the root goal of a coinductive cycle into the global cache. /// @@ -47,7 +50,7 @@ pub(super) struct SearchGraph<'tcx> { /// /// An element is *deeper* in the stack if its index is *lower*. stack: IndexVec>, - provisional_cache: ProvisionalCache<'tcx>, + stack_entries: FxHashMap, StackDepth>, } impl<'tcx> SearchGraph<'tcx> { @@ -56,7 +59,7 @@ impl<'tcx> SearchGraph<'tcx> { mode, local_overflow_limit: tcx.recursion_limit().0.checked_ilog2().unwrap_or(0) as usize, stack: Default::default(), - provisional_cache: ProvisionalCache::empty(), + stack_entries: Default::default(), } } @@ -85,6 +88,7 @@ impl<'tcx> SearchGraph<'tcx> { /// would cause us to not track overflow and recursion depth correctly. fn pop_stack(&mut self) -> StackEntry<'tcx> { let elem = self.stack.pop().unwrap(); + assert!(self.stack_entries.remove(&elem.input).is_some()); if let Some(last) = self.stack.raw.last_mut() { last.reached_depth = last.reached_depth.max(elem.reached_depth); last.encountered_overflow |= elem.encountered_overflow; @@ -104,22 +108,17 @@ impl<'tcx> SearchGraph<'tcx> { } pub(super) fn is_empty(&self) -> bool { - self.stack.is_empty() && self.provisional_cache.is_empty() + self.stack.is_empty() } /// Whether we're currently in a cycle. This should only be used /// for debug assertions. pub(super) fn in_cycle(&self) -> bool { if let Some(stack_depth) = self.stack.last_index() { - // Either the current goal on the stack is the root of a cycle... - if self.stack[stack_depth].has_been_used { - return true; - } - - // ...or it depends on a goal with a lower depth. - let current_goal = self.stack[stack_depth].input; - let entry_index = self.provisional_cache.lookup_table[¤t_goal]; - self.provisional_cache.entries[entry_index].depth != stack_depth + // Either the current goal on the stack is the root of a cycle + // or it depends on a goal with a lower depth. + self.stack[stack_depth].has_been_used + || self.stack[stack_depth].cycle_root_depth != stack_depth } else { false } @@ -211,9 +210,8 @@ impl<'tcx> SearchGraph<'tcx> { } } - // Look at the provisional cache to detect cycles. - let cache = &mut self.provisional_cache; - match cache.lookup_table.entry(input) { + // Check whether we're in a cycle. + match self.stack_entries.entry(input) { // No entry, we push this goal on the stack and try to prove it. Entry::Vacant(v) => { let depth = self.stack.next_index(); @@ -221,14 +219,14 @@ impl<'tcx> SearchGraph<'tcx> { input, available_depth, reached_depth: depth, + cycle_root_depth: depth, encountered_overflow: false, has_been_used: false, + provisional_result: None, cycle_participants: Default::default(), }; assert_eq!(self.stack.push(entry), depth); - let entry_index = - cache.entries.push(ProvisionalEntry { response: None, depth, input }); - v.insert(entry_index); + v.insert(depth); } // We have a nested goal which relies on a goal `root` deeper in the stack. // @@ -239,41 +237,50 @@ impl<'tcx> SearchGraph<'tcx> { // // Finally we can return either the provisional response for that goal if we have a // coinductive cycle or an ambiguous result if the cycle is inductive. - Entry::Occupied(entry_index) => { + Entry::Occupied(entry) => { inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CacheHit( CacheHit::Provisional, )); - let entry_index = *entry_index.get(); - let stack_depth = cache.depth(entry_index); + let stack_depth = *entry.get(); debug!("encountered cycle with depth {stack_depth:?}"); - - cache.add_dependency_of_leaf_on(entry_index); - let mut iter = self.stack.iter_mut(); - let root = iter.nth(stack_depth.as_usize()).unwrap(); - for e in iter { - root.cycle_participants.insert(e.input); + // We start by updating the root depth of all cycle participants, and + // add all cycle participants to the root. + let root_depth = self.stack[stack_depth].cycle_root_depth; + let (prev, participants) = self.stack.raw.split_at_mut(stack_depth.as_usize() + 1); + let root = &mut prev[root_depth.as_usize()]; + for entry in participants { + debug_assert!(entry.cycle_root_depth >= root_depth); + entry.cycle_root_depth = root_depth; + root.cycle_participants.insert(entry.input); + // FIXME(@lcnr): I believe that this line is needed as we could + // otherwise access a cache entry for the root of a cycle while + // computing the result for a cycle participant. This can result + // in unstable results due to incompleteness. + // + // However, a test for this would be an even more complex version of + // tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs. + // I did not bother to write such a test and we have no regression test + // for this. It would be good to have such a test :) + #[allow(rustc::potential_query_instability)] + root.cycle_participants.extend(entry.cycle_participants.drain()); } - // If we're in a cycle, we have to retry proving the current goal - // until we reach a fixpoint. + // If we're in a cycle, we have to retry proving the cycle head + // until we reach a fixpoint. It is not enough to simply retry the + // `root` goal of this cycle. + // + // See tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs + // for an example. self.stack[stack_depth].has_been_used = true; - return if let Some(result) = cache.provisional_result(entry_index) { + return if let Some(result) = self.stack[stack_depth].provisional_result { result } else { - // If we don't have a provisional result yet, the goal has to - // still be on the stack. - let mut goal_on_stack = false; - let mut is_coinductive = true; - for entry in self.stack.raw[stack_depth.index()..] + // If we don't have a provisional result yet we're in the first iteration, + // so we start with no constraints. + let is_coinductive = self.stack.raw[stack_depth.index()..] .iter() - .skip_while(|entry| entry.input != input) - { - goal_on_stack = true; - is_coinductive &= entry.input.value.goal.predicate.is_coinductive(tcx); - } - debug_assert!(goal_on_stack); - + .all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx)); if is_coinductive { Self::response_no_constraints(tcx, input, Certainty::Yes) } else { @@ -294,40 +301,25 @@ impl<'tcx> SearchGraph<'tcx> { // of the previous iteration is equal to the final result, at which // point we are done. for _ in 0..self.local_overflow_limit() { - let response = prove_goal(self, inspect); + let result = prove_goal(self, inspect); // Check whether the current goal is the root of a cycle and whether // we have to rerun because its provisional result differed from the // final result. - // - // Also update the response for this goal stored in the provisional - // cache. let stack_entry = self.pop_stack(); debug_assert_eq!(stack_entry.input, input); - let cache = &mut self.provisional_cache; - let provisional_entry_index = - *cache.lookup_table.get(&stack_entry.input).unwrap(); - let provisional_entry = &mut cache.entries[provisional_entry_index]; if stack_entry.has_been_used - && provisional_entry.response.map_or(true, |r| r != response) + && stack_entry.provisional_result.map_or(true, |r| r != result) { - // If so, update the provisional result for this goal and remove - // all entries whose result depends on this goal from the provisional - // cache... - // - // That's not completely correct, as a nested goal can also only - // depend on a goal which is lower in the stack so it doesn't - // actually depend on the current goal. This should be fairly - // rare and is hopefully not relevant for performance. - provisional_entry.response = Some(response); - #[allow(rustc::potential_query_instability)] - cache.lookup_table.retain(|_key, index| *index <= provisional_entry_index); - cache.entries.truncate(provisional_entry_index.index() + 1); - - // ...and finally push our goal back on the stack and reevaluate it. - self.stack.push(StackEntry { has_been_used: false, ..stack_entry }); + // If so, update its provisional result and reevaluate it. + let depth = self.stack.push(StackEntry { + has_been_used: false, + provisional_result: Some(result), + ..stack_entry + }); + assert_eq!(self.stack_entries.insert(input, depth), None); } else { - return (stack_entry, response); + return (stack_entry, result); } } @@ -343,17 +335,7 @@ impl<'tcx> SearchGraph<'tcx> { // // It is not possible for any nested goal to depend on something deeper on the // stack, as this would have also updated the depth of the current goal. - let cache = &mut self.provisional_cache; - let provisional_entry_index = *cache.lookup_table.get(&input).unwrap(); - let provisional_entry = &mut cache.entries[provisional_entry_index]; - let depth = provisional_entry.depth; - if depth == self.stack.next_index() { - for (i, entry) in cache.entries.drain_enumerated(provisional_entry_index.index()..) { - let actual_index = cache.lookup_table.remove(&entry.input); - debug_assert_eq!(Some(i), actual_index); - debug_assert!(entry.depth == depth); - } - + if final_entry.cycle_root_depth == self.stack.next_index() { // When encountering a cycle, both inductive and coinductive, we only // move the root into the global cache. We also store all other cycle // participants involved. @@ -371,8 +353,6 @@ impl<'tcx> SearchGraph<'tcx> { dep_node, result, ) - } else { - provisional_entry.response = Some(result); } result diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 2a333a4f0e3ef..2a586f810d629 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -3211,7 +3211,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let name = match self.tcx.opaque_type_origin(def_id.expect_local()) { hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => { - format!("opaque type") + "opaque type".to_string() } hir::OpaqueTyOrigin::TyAlias { .. } => { format!("`{}`", self.tcx.def_path_debug_str(def_id)) diff --git a/compiler/stable_mir/src/fold.rs b/compiler/stable_mir/src/fold.rs index 16ae62311aaf0..6471b2c2a3a5e 100644 --- a/compiler/stable_mir/src/fold.rs +++ b/compiler/stable_mir/src/fold.rs @@ -4,17 +4,20 @@ use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind, - GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, + GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst, }; pub trait Folder: Sized { type Break; - fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + fn fold_ty(&mut self, ty: &Ty) -> ControlFlow { ty.super_fold(self) } fn fold_const(&mut self, c: &Const) -> ControlFlow { c.super_fold(self) } + fn fold_reg(&mut self, reg: &Region) -> ControlFlow { + reg.super_fold(self) + } } pub trait Foldable: Sized + Clone { @@ -26,7 +29,7 @@ pub trait Foldable: Sized + Clone { impl Foldable for Ty { fn fold(&self, folder: &mut V) -> ControlFlow { - folder.visit_ty(self) + folder.fold_ty(self) } fn super_fold(&self, folder: &mut V) -> ControlFlow { let mut kind = self.kind(); @@ -81,7 +84,7 @@ impl Foldable for UnevaluatedConst { impl Foldable for ConstDef { fn super_fold(&self, _folder: &mut V) -> ControlFlow { - ControlFlow::Continue(self.clone()) + ControlFlow::Continue(*self) } } @@ -96,7 +99,7 @@ impl Foldable for Option { impl Foldable for Promoted { fn super_fold(&self, _folder: &mut V) -> ControlFlow { - ControlFlow::Continue(self.clone()) + ControlFlow::Continue(*self) } } @@ -106,6 +109,15 @@ impl Foldable for GenericArgs { } } +impl Foldable for Region { + fn fold(&self, folder: &mut V) -> ControlFlow { + folder.fold_reg(self) + } + fn super_fold(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(self.clone()) + } +} + impl Foldable for GenericArgKind { fn super_fold(&self, folder: &mut V) -> ControlFlow { let mut this = self.clone(); @@ -136,7 +148,10 @@ impl Foldable for RigidTy { } RigidTy::Slice(inner) => *inner = inner.fold(folder)?, RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?, - RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?, + RigidTy::Ref(reg, ty, _) => { + *reg = reg.fold(folder)?; + *ty = ty.fold(folder)? + } RigidTy::FnDef(_, args) => *args = args.fold(folder)?, RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?, RigidTy::Closure(_, args) => *args = args.fold(folder)?, @@ -214,7 +229,7 @@ pub enum Never {} impl Folder for GenericArgs { type Break = Never; - fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { + fn fold_ty(&mut self, ty: &Ty) -> ControlFlow { ControlFlow::Continue(match ty.kind() { TyKind::Param(p) => self[p], _ => *ty, diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 82007e3068340..6029e3c11adef 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1,7 +1,7 @@ use super::{ mir::Safety, mir::{Body, Mutability}, - with, AllocId, DefId, + with, AllocId, DefId, Symbol, }; use crate::Opaque; use std::fmt::{self, Debug, Formatter}; @@ -34,7 +34,46 @@ pub struct Const { } type Ident = Opaque; -pub type Region = Opaque; + +#[derive(Debug, Clone)] +pub struct Region { + pub kind: RegionKind, +} + +#[derive(Debug, Clone)] +pub enum RegionKind { + ReEarlyBound(EarlyBoundRegion), + ReLateBound(DebruijnIndex, BoundRegion), + ReStatic, + RePlaceholder(Placeholder), + ReErased, +} + +pub(crate) type DebruijnIndex = u32; + +#[derive(Debug, Clone)] +pub struct EarlyBoundRegion { + pub def_id: RegionDef, + pub index: u32, + pub name: Symbol, +} + +pub(crate) type BoundVar = u32; + +#[derive(Debug, Clone)] +pub struct BoundRegion { + pub var: BoundVar, + pub kind: BoundRegionKind, +} + +pub(crate) type UniverseIndex = u32; + +#[derive(Debug, Clone)] +pub struct Placeholder { + pub universe: UniverseIndex, + pub bound: T, +} + #[derive(Clone, Copy, PartialEq, Eq)] pub struct Span(pub usize); @@ -152,6 +191,9 @@ pub struct ConstDef(pub DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct ImplDef(pub DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct RegionDef(pub DefId); + #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 9c3b4cd994a48..961009581388d 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -4,7 +4,7 @@ use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - Promoted, RigidTy, TermKind, Ty, UnevaluatedConst, + Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; pub trait Visitor: Sized { @@ -15,6 +15,9 @@ pub trait Visitor: Sized { fn visit_const(&mut self, c: &Const) -> ControlFlow { c.super_visit(self) } + fn visit_reg(&mut self, reg: &Region) -> ControlFlow { + reg.super_visit(self) + } } pub trait Visitable { @@ -101,6 +104,16 @@ impl Visitable for GenericArgs { } } +impl Visitable for Region { + fn visit(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_reg(self) + } + + fn super_visit(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + impl Visitable for GenericArgKind { fn super_visit(&self, visitor: &mut V) -> ControlFlow { match self { @@ -128,7 +141,10 @@ impl Visitable for RigidTy { } RigidTy::Slice(inner) => inner.visit(visitor), RigidTy::RawPtr(ty, _) => ty.visit(visitor), - RigidTy::Ref(_, ty, _) => ty.visit(visitor), + RigidTy::Ref(reg, ty, _) => { + reg.visit(visitor); + ty.visit(visitor) + } RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), RigidTy::Closure(_, args) => args.visit(visitor), diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0fb06b16655b3..8dbaca223aa90 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2408,6 +2408,27 @@ impl From for Rc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "CURRENT_RUSTC_VERSION")] +impl From<[T; N]> for Rc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Rc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Rc`. + /// + /// # Example + /// + /// ``` + /// # use std::rc::Rc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Rc<[i32]> = Rc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Rc<[T]> { + Rc::<[T; N]>::from(v) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Rc<[T]> { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c53e9a5dd7abe..61f4bfc54b0e0 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1618,7 +1618,7 @@ impl Arc { #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn weak_count(this: &Self) -> usize { - let cnt = this.inner().weak.load(Acquire); + let cnt = this.inner().weak.load(Relaxed); // If the weak count is currently locked, the value of the // count was 0 just before taking the lock. if cnt == usize::MAX { 0 } else { cnt - 1 } @@ -1648,7 +1648,7 @@ impl Arc { #[must_use] #[stable(feature = "arc_counts", since = "1.15.0")] pub fn strong_count(this: &Self) -> usize { - this.inner().strong.load(Acquire) + this.inner().strong.load(Relaxed) } /// Increments the strong reference count on the `Arc` associated with the @@ -2803,7 +2803,7 @@ impl Weak { #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { - if let Some(inner) = self.inner() { inner.strong.load(Acquire) } else { 0 } + if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 } } /// Gets an approximation of the number of `Weak` pointers pointing to this @@ -2822,7 +2822,7 @@ impl Weak { pub fn weak_count(&self) -> usize { if let Some(inner) = self.inner() { let weak = inner.weak.load(Acquire); - let strong = inner.strong.load(Acquire); + let strong = inner.strong.load(Relaxed); if strong == 0 { 0 } else { @@ -3269,6 +3269,27 @@ impl From for Arc { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "shared_from_array", since = "CURRENT_RUSTC_VERSION")] +impl From<[T; N]> for Arc<[T]> { + /// Converts a [`[T; N]`](prim@array) into an `Arc<[T]>`. + /// + /// The conversion moves the array into a newly allocated `Arc`. + /// + /// # Example + /// + /// ``` + /// # use std::sync::Arc; + /// let original: [i32; 3] = [1, 2, 3]; + /// let shared: Arc<[i32]> = Arc::from(original); + /// assert_eq!(&[1, 2, 3], &shared[..]); + /// ``` + #[inline] + fn from(v: [T; N]) -> Arc<[T]> { + Arc::<[T; N]>::from(v) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] impl From<&[T]> for Arc<[T]> { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 02331db33412b..6f0cd5316a082 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3154,6 +3154,36 @@ impl From<&mut [T]> for Vec { } } +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +impl From<&[T; N]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); + /// ``` + fn from(s: &[T; N]) -> Vec { + Self::from(s.as_slice()) + } +} + +#[cfg(not(no_global_oom_handling))] +#[stable(feature = "vec_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut [T; N]> for Vec { + /// Allocate a `Vec` and fill it by cloning `s`'s items. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); + /// ``` + fn from(s: &mut [T; N]) -> Vec { + Self::from(s.as_mut_slice()) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_array", since = "1.44.0")] impl From<[T; N]> for Vec { diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 9cb27899f1091..d44dcfbf67301 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2562,3 +2562,13 @@ fn test_box_zero_allocator() { // Ensure all ZSTs have been freed. assert!(alloc.state.borrow().0.is_empty()); } + +#[test] +fn test_vec_from_array_ref() { + assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); +} + +#[test] +fn test_vec_from_array_mut_ref() { + assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); +} diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 33226b07e0427..360806167671d 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -291,9 +291,9 @@ pub macro PartialEq($item:item) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Eq"] pub trait Eq: PartialEq { - // this method is used solely by #[deriving] to assert - // that every component of a type implements #[deriving] - // itself, the current deriving infrastructure means doing this + // this method is used solely by #[derive(Eq)] to assert + // that every component of a type implements `Eq` + // itself. The current deriving infrastructure means doing this // assertion without using a method on this trait is nearly // impossible. // diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 8204b3855bd7e..fc91d1afc4315 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -112,9 +112,9 @@ pub trait Write { /// /// # Errors /// - /// This function will return an instance of [`Error`] on error. + /// This function will return an instance of [`std::fmt::Error`][Error] on error. /// - /// The purpose of std::fmt::Error is to abort the formatting operation when the underlying + /// The purpose of that error is to abort the formatting operation when the underlying /// destination encounters some error preventing it from accepting more text; it should /// generally be propagated rather than handled, at least when implementing formatting traits. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 8b04bafcda54a..be734a9ba5298 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -178,6 +178,7 @@ #![feature(ip)] #![feature(ip_bits)] #![feature(is_ascii_octdigit)] +#![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 1f43520e1b30a..3cbb55af3bc66 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -898,6 +898,30 @@ macro_rules! int_impl { acc.checked_mul(base) } + /// Returns the square root of the number, rounded down. + /// + /// Returns `None` if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_isqrt(self) -> Option { + if self < 0 { + None + } else { + Some((self as $UnsignedT).isqrt() as Self) + } + } + /// Saturating integer addition. Computes `self + rhs`, saturating at the numeric /// bounds instead of overflowing. /// @@ -2061,6 +2085,36 @@ macro_rules! int_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Panics + /// + /// This function will panic if `self` is negative. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + // I would like to implement it as + // ``` + // self.checked_isqrt().expect("argument of integer square root must be non-negative") + // ``` + // but `expect` is not yet stable as a `const fn`. + match self.checked_isqrt() { + Some(sqrt) => sqrt, + None => panic!("argument of integer square root must be non-negative"), + } + } + /// Calculates the quotient of Euclidean division of `self` by `rhs`. /// /// This computes the integer `q` such that `self = q * rhs + r`, with diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 7cbef9e779375..a9c5312a1c02b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1995,6 +1995,54 @@ macro_rules! uint_impl { acc * base } + /// Returns the square root of the number, rounded down. + /// + /// # Examples + /// + /// Basic usage: + /// ``` + /// #![feature(isqrt)] + #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] + /// ``` + #[unstable(feature = "isqrt", issue = "116226")] + #[rustc_const_unstable(feature = "isqrt", issue = "116226")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn isqrt(self) -> Self { + if self < 2 { + return self; + } + + // The algorithm is based on the one presented in + // + // which cites as source the following C code: + // . + + let mut op = self; + let mut res = 0; + let mut one = 1 << (self.ilog2() & !1); + + while one != 0 { + if op >= res + one { + op -= res + one; + res = (res >> 1) + one; + } else { + res >>= 1; + } + one >>= 2; + } + + // SAFETY: the result is positive and fits in an integer with half as many bits. + // Inform the optimizer about it. + unsafe { + intrinsics::assume(0 < res); + intrinsics::assume(res < 1 << (Self::BITS / 2)); + } + + res + } + /// Performs Euclidean division. /// /// Since, for the positive integers, all common diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index ee69d89a4b720..9af8f1228f0b6 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -607,7 +607,16 @@ impl *const T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: #method.offset /// @@ -616,7 +625,7 @@ impl *const T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -646,6 +655,14 @@ impl *const T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -703,7 +720,7 @@ impl *const T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6d623b82c1cfe..109c286929b4e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -781,7 +781,16 @@ impl *mut T { /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes divided by `mem::size_of::()`. /// - /// This function is the inverse of [`offset`]. + /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::() as isize)`, + /// except that it has a lot more opportunities for UB, in exchange for the compiler + /// better understanding what you are doing. + /// + /// The primary motivation of this method is for computing the `len` of an array/slice + /// of `T` that you are currently representing as a "start" and "end" pointer + /// (and "end" is "one past the end" of the array). + /// In that case, `end.offset_from(start)` gets you the length of the array. + /// + /// All of the following safety requirements are trivially satisfied for this usecase. /// /// [`offset`]: pointer#method.offset-1 /// @@ -790,7 +799,7 @@ impl *mut T { /// If any of the following conditions are violated, the result is Undefined /// Behavior: /// - /// * Both the starting and other pointer must be either in bounds or one + /// * Both `self` and `origin` must be either in bounds or one /// byte past the end of the same [allocated object]. /// /// * Both pointers must be *derived from* a pointer to the same object. @@ -820,6 +829,14 @@ impl *mut T { /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on /// such large allocations either.) /// + /// The requirement for pointers to be derived from the same allocated object is primarily + /// needed for `const`-compatibility: the distance between pointers into *different* allocated + /// objects is not known at compile-time. However, the requirement also exists at + /// runtime and may be exploited by optimizations. If you wish to compute the difference between + /// pointers that are not guaranteed to be from the same allocation, use `(self as isize - + /// origin as isize) / mem::size_of::()`. + // FIXME: recommend `addr()` instead of `as usize` once that is stable. + /// /// [`add`]: #method.add /// [allocated object]: crate::ptr#allocated-object /// @@ -875,7 +892,7 @@ impl *mut T { /// units of **bytes**. /// /// This is purely a convenience for casting to a `u8` pointer and - /// using [offset_from][pointer::offset_from] on it. See that method for + /// using [`offset_from`][pointer::offset_from] on it. See that method for /// documentation and safety requirements. /// /// For non-`Sized` pointees this operation considers only the data pointers, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0d635aced85bf..a19fcf93c4d90 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3410,7 +3410,7 @@ impl [T] { /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); /// ``` /// - /// Rotate a subslice: + /// Rotating a subslice: /// /// ``` /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index 3f3e19c55d4ba..ff538d55c6079 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -2,6 +2,8 @@ use core::fmt; use core::future::Future; +use core::marker::Tuple; +use core::ops::{Generator, GeneratorState}; use core::pin::Pin; use core::task::{Context, Poll}; @@ -168,10 +170,52 @@ impl From for Exclusive { } #[unstable(feature = "exclusive_wrapper", issue = "98407")] -impl Future for Exclusive { +impl FnOnce for Exclusive +where + F: FnOnce, + Args: Tuple, +{ + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + self.into_inner().call_once(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl FnMut for Exclusive +where + F: FnMut, + Args: Tuple, +{ + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + self.get_mut().call_mut(args) + } +} + +#[unstable(feature = "exclusive_wrapper", issue = "98407")] +impl Future for Exclusive +where + T: Future + ?Sized, +{ type Output = T::Output; + #[inline] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.get_pin_mut().poll(cx) } } + +#[unstable(feature = "generator_trait", issue = "43122")] // also #98407 +impl Generator for Exclusive +where + G: Generator + ?Sized, +{ + type Yield = G::Yield; + type Return = G::Return; + + #[inline] + fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState { + G::resume(self.get_pin_mut(), arg) + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 773f2b955d849..e4003a208bc98 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -56,6 +56,7 @@ #![feature(min_specialization)] #![feature(numfmt)] #![feature(num_midpoint)] +#![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] #![feature(std_internals)] diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 439bbe6699781..165d9a296176e 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -290,6 +290,38 @@ macro_rules! int_module { assert_eq!(r.saturating_pow(0), 1 as $T); } + #[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); + } + + #[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_div_floor() { let a: $T = 8; diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 7d6203db0b940..955440647eb98 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -206,6 +206,35 @@ macro_rules! uint_module { assert_eq!(r.saturating_pow(2), MAX); } + #[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); + } + + #[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); + } + + for n in ($T::MAX - 255)..=$T::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); + } + } + #[test] fn test_div_floor() { assert_eq!((8 as $T).div_floor(3), 2); diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 2b40b672d9f0a..5d9f7430ca2cb 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -434,6 +434,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStdin` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdin { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStdin { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStdin::from_inner(pipe) + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsFd for crate::process::ChildStdout { #[inline] @@ -450,6 +464,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStdout` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdout { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStdout { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStdout::from_inner(pipe) + } +} + #[stable(feature = "io_safety", since = "1.63.0")] impl AsFd for crate::process::ChildStderr { #[inline] @@ -466,6 +494,20 @@ impl From for OwnedFd { } } +/// Create a `ChildStderr` from the provided `OwnedFd`. +/// +/// The provided file descriptor must point to a pipe +/// with the `CLOEXEC` flag set. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStderr { + #[inline] + fn from(fd: OwnedFd) -> process::ChildStderr { + let fd = sys::fd::FileDesc::from_inner(fd); + let pipe = sys::pipe::AnonPipe::from_inner(fd); + process::ChildStderr::from_inner(pipe) + } +} + /// Returns the OS-assigned process identifier associated with this process's parent. #[must_use] #[stable(feature = "unix_ppid", since = "1.27.0")] diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 6359835cad5d9..c80b9e28499bc 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -116,7 +116,7 @@ impl BorrowedSocket<'_> { let mut info = unsafe { mem::zeroed::() }; let result = unsafe { sys::c::WSADuplicateSocketW( - self.as_raw_socket(), + self.as_raw_socket() as sys::c::SOCKET, sys::c::GetCurrentProcessId(), &mut info, ) @@ -134,7 +134,7 @@ impl BorrowedSocket<'_> { }; if socket != sys::c::INVALID_SOCKET { - unsafe { Ok(OwnedSocket::from_raw_socket(socket)) } + unsafe { Ok(OwnedSocket::from_raw_socket(socket as RawSocket)) } } else { let error = unsafe { sys::c::WSAGetLastError() }; @@ -158,7 +158,7 @@ impl BorrowedSocket<'_> { } unsafe { - let socket = OwnedSocket::from_raw_socket(socket); + let socket = OwnedSocket::from_raw_socket(socket as RawSocket); socket.set_no_inherit()?; Ok(socket) } @@ -211,7 +211,7 @@ impl Drop for OwnedSocket { #[inline] fn drop(&mut self) { unsafe { - let _ = sys::c::closesocket(self.socket); + let _ = sys::c::closesocket(self.socket as sys::c::SOCKET); } } } diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 5d87216ff1b4c..94173825c4af5 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -106,6 +106,45 @@ impl IntoRawHandle for process::ChildStderr { } } +/// Create a `ChildStdin` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdin { + fn from(handle: OwnedHandle) -> process::ChildStdin { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStdin::from_inner(pipe) + } +} + +/// Create a `ChildStdout` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStdout { + fn from(handle: OwnedHandle) -> process::ChildStdout { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStdout::from_inner(pipe) + } +} + +/// Create a `ChildStderr` from the provided `OwnedHandle`. +/// +/// The provided handle must be asynchronous, as reading and +/// writing from and to it is implemented using asynchronous APIs. +#[stable(feature = "child_stream_from_fd", since = "CURRENT_RUSTC_VERSION")] +impl From for process::ChildStderr { + fn from(handle: OwnedHandle) -> process::ChildStderr { + let handle = sys::handle::Handle::from_inner(handle); + let pipe = sys::pipe::AnonPipe::from_inner(handle); + process::ChildStderr::from_inner(pipe) + } +} + /// Windows-specific extensions to [`process::ExitStatus`]. /// /// This trait is sealed: it cannot be implemented outside the standard library. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 948862c2a7ddc..6cf3bd619b255 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -12,9 +12,9 @@ //! use std::process::Command; //! //! let output = Command::new("echo") -//! .arg("Hello world") -//! .output() -//! .expect("Failed to execute command"); +//! .arg("Hello world") +//! .output() +//! .expect("Failed to execute command"); //! //! assert_eq!(b"Hello world\n", output.stdout.as_slice()); //! ``` @@ -154,12 +154,11 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// use std::process::Command; /// /// let mut child = Command::new("/bin/cat") -/// .arg("file.txt") -/// .spawn() -/// .expect("failed to execute child"); +/// .arg("file.txt") +/// .spawn() +/// .expect("failed to execute child"); /// -/// let ecode = child.wait() -/// .expect("failed to wait on child"); +/// let ecode = child.wait().expect("failed to wait on child"); /// /// assert!(ecode.success()); /// ``` @@ -481,15 +480,15 @@ impl fmt::Debug for ChildStderr { /// /// let output = if cfg!(target_os = "windows") { /// Command::new("cmd") -/// .args(["/C", "echo hello"]) -/// .output() -/// .expect("failed to execute process") +/// .args(["/C", "echo hello"]) +/// .output() +/// .expect("failed to execute process") /// } else { /// Command::new("sh") -/// .arg("-c") -/// .arg("echo hello") -/// .output() -/// .expect("failed to execute process") +/// .arg("-c") +/// .arg("echo hello") +/// .output() +/// .expect("failed to execute process") /// }; /// /// let hello = output.stdout; @@ -502,8 +501,7 @@ impl fmt::Debug for ChildStderr { /// use std::process::Command; /// /// let mut echo_hello = Command::new("sh"); -/// echo_hello.arg("-c") -/// .arg("echo hello"); +/// echo_hello.arg("-c").arg("echo hello"); /// let hello_1 = echo_hello.output().expect("failed to execute process"); /// let hello_2 = echo_hello.output().expect("failed to execute process"); /// ``` @@ -576,8 +574,8 @@ impl Command { /// use std::process::Command; /// /// Command::new("sh") - /// .spawn() - /// .expect("sh command failed to start"); + /// .spawn() + /// .expect("sh command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn new>(program: S) -> Command { @@ -620,10 +618,10 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .arg("-l") - /// .arg("-a") - /// .spawn() - /// .expect("ls command failed to start"); + /// .arg("-l") + /// .arg("-a") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn arg>(&mut self, arg: S) -> &mut Command { @@ -650,9 +648,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .args(["-l", "-a"]) - /// .spawn() - /// .expect("ls command failed to start"); + /// .args(["-l", "-a"]) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn args(&mut self, args: I) -> &mut Command @@ -688,9 +686,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env("PATH", "/bin") - /// .spawn() - /// .expect("ls command failed to start"); + /// .env("PATH", "/bin") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env(&mut self, key: K, val: V) -> &mut Command @@ -731,12 +729,12 @@ impl Command { /// ).collect(); /// /// Command::new("printenv") - /// .stdin(Stdio::null()) - /// .stdout(Stdio::inherit()) - /// .env_clear() - /// .envs(&filtered_env) - /// .spawn() - /// .expect("printenv failed to start"); + /// .stdin(Stdio::null()) + /// .stdout(Stdio::inherit()) + /// .env_clear() + /// .envs(&filtered_env) + /// .spawn() + /// .expect("printenv failed to start"); /// ``` #[stable(feature = "command_envs", since = "1.19.0")] pub fn envs(&mut self, vars: I) -> &mut Command @@ -772,9 +770,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env_remove("PATH") - /// .spawn() - /// .expect("ls command failed to start"); + /// .env_remove("PATH") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_remove>(&mut self, key: K) -> &mut Command { @@ -802,9 +800,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .env_clear() - /// .spawn() - /// .expect("ls command failed to start"); + /// .env_clear() + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn env_clear(&mut self) -> &mut Command { @@ -830,9 +828,9 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .current_dir("/bin") - /// .spawn() - /// .expect("ls command failed to start"); + /// .current_dir("/bin") + /// .spawn() + /// .expect("ls command failed to start"); /// ``` /// /// [`canonicalize`]: crate::fs::canonicalize @@ -861,9 +859,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stdin(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stdin(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stdin>(&mut self, cfg: T) -> &mut Command { @@ -890,9 +888,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stdout(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stdout(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stdout>(&mut self, cfg: T) -> &mut Command { @@ -919,9 +917,9 @@ impl Command { /// use std::process::{Command, Stdio}; /// /// Command::new("ls") - /// .stderr(Stdio::null()) - /// .spawn() - /// .expect("ls command failed to start"); + /// .stderr(Stdio::null()) + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn stderr>(&mut self, cfg: T) -> &mut Command { @@ -941,8 +939,8 @@ impl Command { /// use std::process::Command; /// /// Command::new("ls") - /// .spawn() - /// .expect("ls command failed to start"); + /// .spawn() + /// .expect("ls command failed to start"); /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn spawn(&mut self) -> io::Result { @@ -963,9 +961,9 @@ impl Command { /// use std::process::Command; /// use std::io::{self, Write}; /// let output = Command::new("/bin/cat") - /// .arg("file.txt") - /// .output() - /// .expect("failed to execute process"); + /// .arg("file.txt") + /// .output() + /// .expect("failed to execute process"); /// /// println!("status: {}", output.status); /// io::stdout().write_all(&output.stdout).unwrap(); @@ -990,9 +988,9 @@ impl Command { /// use std::process::Command; /// /// let status = Command::new("/bin/cat") - /// .arg("file.txt") - /// .status() - /// .expect("failed to execute process"); + /// .arg("file.txt") + /// .status() + /// .expect("failed to execute process"); /// /// println!("process finished with: {status}"); /// @@ -1618,9 +1616,9 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("ls") - /// .arg("/dev/nonexistent") - /// .status() - /// .expect("ls could not be executed"); + /// .arg("/dev/nonexistent") + /// .status() + /// .expect("ls could not be executed"); /// /// println!("ls: {status}"); /// status.exit_ok().expect_err("/dev/nonexistent could be listed!"); @@ -1640,9 +1638,9 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("mkdir") - /// .arg("projects") - /// .status() - /// .expect("failed to execute mkdir"); + /// .arg("projects") + /// .status() + /// .expect("failed to execute mkdir"); /// /// if status.success() { /// println!("'projects/' directory created"); @@ -1673,13 +1671,13 @@ impl ExitStatus { /// use std::process::Command; /// /// let status = Command::new("mkdir") - /// .arg("projects") - /// .status() - /// .expect("failed to execute mkdir"); + /// .arg("projects") + /// .status() + /// .expect("failed to execute mkdir"); /// /// match status.code() { /// Some(code) => println!("Exited with status code: {code}"), - /// None => println!("Process terminated by signal") + /// None => println!("Process terminated by signal") /// } /// ``` #[must_use] @@ -1809,9 +1807,9 @@ impl ExitStatusError { } #[unstable(feature = "exit_status_error", issue = "84908")] -impl Into for ExitStatusError { - fn into(self) -> ExitStatus { - ExitStatus(self.0.into()) +impl From for ExitStatus { + fn from(error: ExitStatusError) -> Self { + Self(error.0.into()) } } diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs index 1239c65a483be..33db24e77e4da 100644 --- a/library/std/src/sys/unix/pipe.rs +++ b/library/std/src/sys/unix/pipe.rs @@ -3,7 +3,7 @@ use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; use crate::sys::{cvt, cvt_r}; -use crate::sys_common::IntoInner; +use crate::sys_common::{FromInner, IntoInner}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -159,3 +159,9 @@ impl FromRawFd for AnonPipe { Self(FromRawFd::from_raw_fd(raw_fd)) } } + +impl FromInner for AnonPipe { + fn from_inner(fd: FileDesc) -> Self { + Self(fd) + } +} diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index d9ccba0e9da76..f3637cbb981dc 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -46,10 +46,6 @@ pub use FD_SET as fd_set; pub use LINGER as linger; pub use TIMEVAL as timeval; -pub type CONDITION_VARIABLE = RTL_CONDITION_VARIABLE; -pub type SRWLOCK = RTL_SRWLOCK; -pub type INIT_ONCE = RTL_RUN_ONCE; - pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() }; pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() }; pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() }; @@ -224,7 +220,7 @@ pub unsafe extern "system" fn ReadFileEx( ) -> BOOL { windows_sys::ReadFileEx( hFile.as_raw_handle(), - lpBuffer, + lpBuffer.cast::(), nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine, diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 5469ba42eb11a..0aca37e2d454e 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -1,3 +1,6 @@ +--out windows_sys.rs +--config flatten std +--filter // tidy-alphabetical-start Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION @@ -2108,7 +2111,6 @@ Windows.Win32.Networking.WinSock.WSABASEERR Windows.Win32.Networking.WinSock.WSABUF Windows.Win32.Networking.WinSock.WSACleanup Windows.Win32.Networking.WinSock.WSADATA -Windows.Win32.Networking.WinSock.WSADATA Windows.Win32.Networking.WinSock.WSADuplicateSocketW Windows.Win32.Networking.WinSock.WSAEACCES Windows.Win32.Networking.WinSock.WSAEADDRINUSE @@ -2328,7 +2330,6 @@ Windows.Win32.Storage.FileSystem.FileStandardInfo Windows.Win32.Storage.FileSystem.FileStorageInfo Windows.Win32.Storage.FileSystem.FileStreamInfo Windows.Win32.Storage.FileSystem.FindClose -Windows.Win32.Storage.FileSystem.FindFileHandle Windows.Win32.Storage.FileSystem.FindFirstFileW Windows.Win32.Storage.FileSystem.FindNextFileW Windows.Win32.Storage.FileSystem.FlushFileBuffers @@ -2420,8 +2421,6 @@ Windows.Win32.System.Console.STD_OUTPUT_HANDLE Windows.Win32.System.Console.WriteConsoleW Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128 Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT @@ -2435,7 +2434,6 @@ Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS Windows.Win32.System.Diagnostics.Debug.FormatMessageW Windows.Win32.System.Diagnostics.Debug.M128A Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT -Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT Windows.Win32.System.Environment.FreeEnvironmentStringsW Windows.Win32.System.Environment.GetCommandLineW Windows.Win32.System.Environment.GetCurrentDirectoryW @@ -2456,7 +2454,6 @@ Windows.Win32.System.Kernel.ExceptionContinueExecution Windows.Win32.System.Kernel.ExceptionContinueSearch Windows.Win32.System.Kernel.ExceptionNestedException Windows.Win32.System.Kernel.FLOATING_SAVE_AREA -Windows.Win32.System.Kernel.FLOATING_SAVE_AREA Windows.Win32.System.Kernel.OBJ_DONT_REPARSE Windows.Win32.System.LibraryLoader.GetModuleFileNameW Windows.Win32.System.LibraryLoader.GetModuleHandleA @@ -2482,6 +2479,7 @@ Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime Windows.Win32.System.SystemInformation.GetWindowsDirectoryW Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE Windows.Win32.System.SystemInformation.SYSTEM_INFO +Windows.Win32.System.SystemServices.ALL_PROCESSOR_GROUPS Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH Windows.Win32.System.SystemServices.DLL_THREAD_DETACH Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS @@ -2514,6 +2512,7 @@ Windows.Win32.System.Threading.DeleteProcThreadAttributeList Windows.Win32.System.Threading.DETACHED_PROCESS Windows.Win32.System.Threading.ExitProcess Windows.Win32.System.Threading.EXTENDED_STARTUPINFO_PRESENT +Windows.Win32.System.Threading.GetActiveProcessorCount Windows.Win32.System.Threading.GetCurrentProcess Windows.Win32.System.Threading.GetCurrentProcessId Windows.Win32.System.Threading.GetCurrentThread @@ -2542,9 +2541,6 @@ Windows.Win32.System.Threading.PROFILE_USER Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS Windows.Win32.System.Threading.ReleaseSRWLockExclusive Windows.Win32.System.Threading.ReleaseSRWLockShared -Windows.Win32.System.Threading.RTL_CONDITION_VARIABLE -Windows.Win32.System.Threading.RTL_RUN_ONCE -Windows.Win32.System.Threading.RTL_SRWLOCK Windows.Win32.System.Threading.SetThreadStackGuarantee Windows.Win32.System.Threading.Sleep Windows.Win32.System.Threading.SleepConditionVariableSRW @@ -2584,8 +2580,6 @@ Windows.Win32.System.Threading.WaitForMultipleObjects Windows.Win32.System.Threading.WaitForSingleObject Windows.Win32.System.Threading.WakeAllConditionVariable Windows.Win32.System.Threading.WakeConditionVariable -Windows.Win32.System.WindowsProgramming.IO_STATUS_BLOCK -Windows.Win32.System.WindowsProgramming.OBJECT_ATTRIBUTES Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW // tidy-alphabetical-end diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index b24f6dc900fc5..851d15915c7d1 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -4,7 +4,7 @@ // regenerate the bindings. // // ignore-tidy-filelength -// Bindings generated by `windows-bindgen` 0.49.0 +// Bindings generated by `windows-bindgen` 0.51.1 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] #[link(name = "advapi32")] @@ -32,11 +32,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -189,18 +189,15 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn FindClose(hfindfile: FindFileHandle) -> BOOL; + pub fn FindClose(hfindfile: HANDLE) -> BOOL; } #[link(name = "kernel32")] extern "system" { - pub fn FindFirstFileW( - lpfilename: PCWSTR, - lpfindfiledata: *mut WIN32_FIND_DATAW, - ) -> FindFileHandle; + pub fn FindFirstFileW(lpfilename: PCWSTR, lpfindfiledata: *mut WIN32_FIND_DATAW) -> HANDLE; } #[link(name = "kernel32")] extern "system" { - pub fn FindNextFileW(hfindfile: FindFileHandle, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; + pub fn FindNextFileW(hfindfile: HANDLE, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; } #[link(name = "kernel32")] extern "system" { @@ -223,6 +220,10 @@ extern "system" { pub fn FreeEnvironmentStringsW(penv: PCWSTR) -> BOOL; } #[link(name = "kernel32")] +extern "system" { + pub fn GetActiveProcessorCount(groupnumber: u16) -> u32; +} +#[link(name = "kernel32")] extern "system" { pub fn GetCommandLineW() -> PCWSTR; } @@ -360,7 +361,7 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceBeginInitialize( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, fpending: *mut BOOL, lpcontext: *mut *mut ::core::ffi::c_void, @@ -369,7 +370,7 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceComplete( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, lpcontext: *const ::core::ffi::c_void, ) -> BOOL; @@ -424,7 +425,7 @@ extern "system" { extern "system" { pub fn ReadFile( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpnumberofbytesread: *mut u32, lpoverlapped: *mut OVERLAPPED, @@ -434,7 +435,7 @@ extern "system" { extern "system" { pub fn ReadFileEx( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpoverlapped: *mut OVERLAPPED, lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, @@ -442,11 +443,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -513,8 +514,8 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn SleepConditionVariableSRW( - conditionvariable: *mut RTL_CONDITION_VARIABLE, - srwlock: *mut RTL_SRWLOCK, + conditionvariable: *mut CONDITION_VARIABLE, + srwlock: *mut SRWLOCK, dwmilliseconds: u32, flags: u32, ) -> BOOL; @@ -549,11 +550,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> BOOLEAN; } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockShared(srwlock: *mut SRWLOCK) -> BOOLEAN; } #[link(name = "kernel32")] extern "system" { @@ -574,19 +575,19 @@ extern "system" { lphandles: *const HANDLE, bwaitall: BOOL, dwmilliseconds: u32, - ) -> WIN32_ERROR; + ) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR; + pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WakeAllConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeAllConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn WakeConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { @@ -847,6 +848,7 @@ impl ::core::clone::Clone for ADDRINFOA { pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16; +pub const ALL_PROCESSOR_GROUPS: u32 = 65535u32; #[repr(C)] pub union ARM64_NT_NEON128 { pub Anonymous: ARM64_NT_NEON128_0, @@ -899,7 +901,17 @@ impl ::core::clone::Clone for BY_HANDLE_FILE_INFORMATION { } pub const CALLBACK_CHUNK_FINISHED: LPPROGRESS_ROUTINE_CALLBACK_REASON = 0u32; pub const CALLBACK_STREAM_SWITCH: LPPROGRESS_ROUTINE_CALLBACK_REASON = 1u32; -pub type COMPARESTRING_RESULT = u32; +pub type COMPARESTRING_RESULT = i32; +#[repr(C)] +pub struct CONDITION_VARIABLE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for CONDITION_VARIABLE {} +impl ::core::clone::Clone for CONDITION_VARIABLE { + fn clone(&self) -> Self { + *self + } +} pub type CONSOLE_MODE = u32; #[repr(C)] pub struct CONSOLE_READCONSOLE_CONTROL { @@ -917,7 +929,7 @@ impl ::core::clone::Clone for CONSOLE_READCONSOLE_CONTROL { #[repr(C)] #[cfg(target_arch = "aarch64")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Cpsr: u32, pub Anonymous: CONTEXT_0, pub Sp: u64, @@ -1004,7 +1016,7 @@ pub struct CONTEXT { pub P4Home: u64, pub P5Home: u64, pub P6Home: u64, - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub MxCsr: u32, pub SegCs: u16, pub SegDs: u16, @@ -1100,7 +1112,7 @@ impl ::core::clone::Clone for CONTEXT_0_0 { #[repr(C)] #[cfg(target_arch = "x86")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Dr0: u32, pub Dr1: u32, pub Dr2: u32, @@ -1134,6 +1146,7 @@ impl ::core::clone::Clone for CONTEXT { *self } } +pub type CONTEXT_FLAGS = u32; pub const CP_UTF8: u32 = 65001u32; pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32; pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32; @@ -1151,9 +1164,9 @@ pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32; pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32; pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32; pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32; -pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2u32; -pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3u32; -pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1u32; +pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2i32; +pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3i32; +pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1i32; pub const DEBUG_ONLY_THIS_PROCESS: PROCESS_CREATION_FLAGS = 2u32; pub const DEBUG_PROCESS: PROCESS_CREATION_FLAGS = 1u32; pub const DELETE: FILE_ACCESS_RIGHTS = 65536u32; @@ -3369,7 +3382,6 @@ pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32; pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32; pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32; pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32; -pub type FindFileHandle = *mut ::core::ffi::c_void; pub type GENERIC_ACCESS_RIGHTS = u32; pub const GENERIC_ALL: GENERIC_ACCESS_RIGHTS = 268435456u32; pub const GENERIC_EXECUTE: GENERIC_ACCESS_RIGHTS = 536870912u32; @@ -3383,6 +3395,12 @@ pub struct GUID { pub data3: u16, pub data4: [u8; 8], } +impl ::core::marker::Copy for GUID {} +impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } +} impl GUID { pub const fn from_u128(uuid: u128) -> Self { Self { @@ -3393,12 +3411,6 @@ impl GUID { } } } -impl ::core::marker::Copy for GUID {} -impl ::core::clone::Clone for GUID { - fn clone(&self) -> Self { - *self - } -} pub type HANDLE = *mut ::core::ffi::c_void; pub type HANDLE_FLAGS = u32; pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32; @@ -3431,6 +3443,16 @@ impl ::core::clone::Clone for IN6_ADDR_0 { pub const INFINITE: u32 = 4294967295u32; pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; +#[repr(C)] +pub union INIT_ONCE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for INIT_ONCE {} +impl ::core::clone::Clone for INIT_ONCE { + fn clone(&self) -> Self { + *self + } +} pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); @@ -3659,10 +3681,10 @@ pub type NTSTATUS = i32; pub struct OBJECT_ATTRIBUTES { pub Length: u32, pub RootDirectory: HANDLE, - pub ObjectName: *mut UNICODE_STRING, + pub ObjectName: *const UNICODE_STRING, pub Attributes: u32, - pub SecurityDescriptor: *mut ::core::ffi::c_void, - pub SecurityQualityOfService: *mut ::core::ffi::c_void, + pub SecurityDescriptor: *const ::core::ffi::c_void, + pub SecurityQualityOfService: *const ::core::ffi::c_void, } impl ::core::marker::Copy for OBJECT_ATTRIBUTES {} impl ::core::clone::Clone for OBJECT_ATTRIBUTES { @@ -3712,8 +3734,8 @@ pub type PCSTR = *const u8; pub type PCWSTR = *const u16; pub type PIO_APC_ROUTINE = ::core::option::Option< unsafe extern "system" fn( - apccontext: *const ::core::ffi::c_void, - iostatusblock: *const IO_STATUS_BLOCK, + apccontext: *mut ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, reserved: u32, ) -> (), >; @@ -3755,36 +3777,6 @@ pub type PSTR = *mut u8; pub type PWSTR = *mut u16; pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; -#[repr(C)] -pub struct RTL_CONDITION_VARIABLE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_CONDITION_VARIABLE {} -impl ::core::clone::Clone for RTL_CONDITION_VARIABLE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub union RTL_RUN_ONCE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_RUN_ONCE {} -impl ::core::clone::Clone for RTL_RUN_ONCE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub struct RTL_SRWLOCK { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_SRWLOCK {} -impl ::core::clone::Clone for RTL_SRWLOCK { - fn clone(&self) -> Self { - *self - } -} pub const SD_BOTH: WINSOCK_SHUTDOWN_HOW = 2i32; pub const SD_RECEIVE: WINSOCK_SHUTDOWN_HOW = 0i32; pub const SD_SEND: WINSOCK_SHUTDOWN_HOW = 1i32; @@ -3821,10 +3813,7 @@ impl ::core::clone::Clone for SOCKADDR { *self } } -#[cfg(target_pointer_width = "32")] -pub type SOCKET = u32; -#[cfg(target_pointer_width = "64")] -pub type SOCKET = u64; +pub type SOCKET = usize; pub const SOCKET_ERROR: i32 = -1i32; pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; pub const SOCK_RAW: WINSOCK_SOCKET_TYPE = 3i32; @@ -3838,6 +3827,16 @@ pub const SO_LINGER: i32 = 128i32; pub const SO_RCVTIMEO: i32 = 4102i32; pub const SO_SNDTIMEO: i32 = 4101i32; pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; +#[repr(C)] +pub struct SRWLOCK { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for SRWLOCK {} +impl ::core::clone::Clone for SRWLOCK { + fn clone(&self) -> Self { + *self + } +} pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; @@ -4008,12 +4007,13 @@ impl ::core::clone::Clone for UNICODE_STRING { pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; -pub const WAIT_ABANDONED: WIN32_ERROR = 128u32; -pub const WAIT_ABANDONED_0: WIN32_ERROR = 128u32; -pub const WAIT_FAILED: WIN32_ERROR = 4294967295u32; -pub const WAIT_IO_COMPLETION: WIN32_ERROR = 192u32; -pub const WAIT_OBJECT_0: WIN32_ERROR = 0u32; -pub const WAIT_TIMEOUT: WIN32_ERROR = 258u32; +pub const WAIT_ABANDONED: WAIT_EVENT = 128u32; +pub const WAIT_ABANDONED_0: WAIT_EVENT = 128u32; +pub type WAIT_EVENT = u32; +pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32; +pub const WAIT_IO_COMPLETION: WAIT_EVENT = 192u32; +pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32; +pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32; pub const WC_ERR_INVALID_CHARS: u32 = 128u32; pub type WIN32_ERROR = u32; #[repr(C)] diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 84c1fbde32d2f..56d0d6c088737 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -143,13 +143,8 @@ impl Handle { ) -> io::Result> { let len = cmp::min(buf.len(), ::MAX as usize) as c::DWORD; let mut amt = 0; - let res = cvt(c::ReadFile( - self.as_raw_handle(), - buf.as_ptr() as c::LPVOID, - len, - &mut amt, - overlapped, - )); + let res = + cvt(c::ReadFile(self.as_raw_handle(), buf.as_mut_ptr(), len, &mut amt, overlapped)); match res { Ok(_) => Ok(Some(amt as usize)), Err(e) => { diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 1ae42cb7eae63..abdcab4247fac 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -117,7 +117,7 @@ impl Socket { }; if socket != c::INVALID_SOCKET { - unsafe { Ok(Self::from_raw_socket(socket)) } + unsafe { Ok(Self::from_raw(socket)) } } else { let error = unsafe { c::WSAGetLastError() }; @@ -133,7 +133,7 @@ impl Socket { } unsafe { - let socket = Self::from_raw_socket(socket); + let socket = Self::from_raw(socket); socket.0.set_no_inherit()?; Ok(socket) } @@ -144,7 +144,7 @@ impl Socket { self.set_nonblocking(true)?; let result = { let (addr, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw_socket(), addr.as_ptr(), len) }; + let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; cvt(result).map(drop) }; self.set_nonblocking(false)?; @@ -170,7 +170,7 @@ impl Socket { let fds = { let mut fds = unsafe { mem::zeroed::() }; fds.fd_count = 1; - fds.fd_array[0] = self.as_raw_socket(); + fds.fd_array[0] = self.as_raw(); fds }; @@ -202,11 +202,11 @@ impl Socket { } pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result { - let socket = unsafe { c::accept(self.as_raw_socket(), storage, len) }; + let socket = unsafe { c::accept(self.as_raw(), storage, len) }; match socket { c::INVALID_SOCKET => Err(last_error()), - _ => unsafe { Ok(Self::from_raw_socket(socket)) }, + _ => unsafe { Ok(Self::from_raw(socket)) }, } } @@ -218,9 +218,8 @@ impl Socket { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let length = cmp::min(buf.capacity(), i32::MAX as usize) as i32; - let result = unsafe { - c::recv(self.as_raw_socket(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) - }; + let result = + unsafe { c::recv(self.as_raw(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) }; match result { c::SOCKET_ERROR => { @@ -257,7 +256,7 @@ impl Socket { let mut flags = 0; let result = unsafe { c::WSARecv( - self.as_raw_socket(), + self.as_raw(), bufs.as_mut_ptr() as *mut c::WSABUF, length, &mut nread, @@ -305,7 +304,7 @@ impl Socket { // do the same on windows to map a shut down socket to returning EOF. let result = unsafe { c::recvfrom( - self.as_raw_socket(), + self.as_raw(), buf.as_mut_ptr() as *mut _, length, flags, @@ -341,7 +340,7 @@ impl Socket { let mut nwritten = 0; let result = unsafe { c::WSASend( - self.as_raw_socket(), + self.as_raw(), bufs.as_ptr() as *const c::WSABUF as *mut _, length, &mut nwritten, @@ -392,14 +391,14 @@ impl Socket { Shutdown::Read => c::SD_RECEIVE, Shutdown::Both => c::SD_BOTH, }; - let result = unsafe { c::shutdown(self.as_raw_socket(), how) }; + let result = unsafe { c::shutdown(self.as_raw(), how) }; cvt(result).map(drop) } pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; let result = - unsafe { c::ioctlsocket(self.as_raw_socket(), c::FIONBIO as c_int, &mut nonblocking) }; + unsafe { c::ioctlsocket(self.as_raw(), c::FIONBIO as c_int, &mut nonblocking) }; cvt(result).map(drop) } @@ -433,8 +432,15 @@ impl Socket { } // This is used by sys_common code to abstract over Windows and Unix. - pub fn as_raw(&self) -> RawSocket { - self.as_inner().as_raw_socket() + pub fn as_raw(&self) -> c::SOCKET { + debug_assert_eq!(mem::size_of::(), mem::size_of::()); + debug_assert_eq!(mem::align_of::(), mem::align_of::()); + self.as_inner().as_raw_socket() as c::SOCKET + } + pub unsafe fn from_raw(raw: c::SOCKET) -> Self { + debug_assert_eq!(mem::size_of::(), mem::size_of::()); + debug_assert_eq!(mem::align_of::(), mem::align_of::()); + Self::from_raw_socket(raw as RawSocket) } } diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index d07147eccc1d3..7624e746f5c89 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -12,7 +12,7 @@ use crate::sys::c; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; use crate::sys::hashmap_random_keys; -use crate::sys_common::IntoInner; +use crate::sys_common::{FromInner, IntoInner}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -28,6 +28,12 @@ impl IntoInner for AnonPipe { } } +impl FromInner for AnonPipe { + fn from_inner(inner: Handle) -> AnonPipe { + Self { inner } + } +} + pub struct Pipes { pub ours: AnonPipe, pub theirs: AnonPipe, diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d58f0d54d3aec..fac0cdf203846 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -41,6 +41,10 @@ def get_cpus(): return 1 +def eprint(*args, **kwargs): + kwargs["file"] = sys.stderr + print(*args, **kwargs) + def get(base, url, path, checksums, verbose=False): with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -57,23 +61,23 @@ def get(base, url, path, checksums, verbose=False): if os.path.exists(path): if verify(path, sha256, False): if verbose: - print("using already-download file", path, file=sys.stderr) + eprint("using already-download file", path) return else: if verbose: - print("ignoring already-download file", - path, "due to failed verification", file=sys.stderr) + eprint("ignoring already-download file", + path, "due to failed verification") os.unlink(path) download(temp_path, "{}/{}".format(base, url), True, verbose) if not verify(temp_path, sha256, verbose): raise RuntimeError("failed verification") if verbose: - print("moving {} to {}".format(temp_path, path), file=sys.stderr) + eprint("moving {} to {}".format(temp_path, path)) shutil.move(temp_path, path) finally: if os.path.isfile(temp_path): if verbose: - print("removing", temp_path, file=sys.stderr) + eprint("removing", temp_path) os.unlink(temp_path) @@ -83,7 +87,7 @@ def download(path, url, probably_big, verbose): _download(path, url, probably_big, verbose, True) return except RuntimeError: - print("\nspurious failure, trying again", file=sys.stderr) + eprint("\nspurious failure, trying again") _download(path, url, probably_big, verbose, False) @@ -94,7 +98,7 @@ def _download(path, url, probably_big, verbose, exception): # - If we are on win32 fallback to powershell # - Otherwise raise the error if appropriate if probably_big or verbose: - print("downloading {}".format(url), file=sys.stderr) + eprint("downloading {}".format(url)) try: if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ: @@ -129,20 +133,20 @@ def _download(path, url, probably_big, verbose, exception): def verify(path, expected, verbose): """Check if the sha256 sum of the given path is valid""" if verbose: - print("verifying", path, file=sys.stderr) + eprint("verifying", path) with open(path, "rb") as source: found = hashlib.sha256(source.read()).hexdigest() verified = found == expected if not verified: - print("invalid checksum:\n" + eprint("invalid checksum:\n" " found: {}\n" - " expected: {}".format(found, expected), file=sys.stderr) + " expected: {}".format(found, expected)) return verified def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): """Unpack the given tarball file""" - print("extracting", tarball, file=sys.stderr) + eprint("extracting", tarball) fname = os.path.basename(tarball).replace(tarball_suffix, "") with contextlib.closing(tarfile.open(tarball)) as tar: for member in tar.getnames(): @@ -155,7 +159,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): dst_path = os.path.join(dst, name) if verbose: - print(" extracting", member, file=sys.stderr) + eprint(" extracting", member) tar.extract(member, dst) src_path = os.path.join(dst, member) if os.path.isdir(src_path) and os.path.exists(dst_path): @@ -167,7 +171,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: - print("running: " + ' '.join(args), file=sys.stderr) + eprint("running: " + ' '.join(args)) sys.stdout.flush() # Ensure that the .exe is used on Windows just in case a Linux ELF has been # compiled in the same directory. @@ -207,8 +211,8 @@ def require(cmd, exit=True, exception=False): if exception: raise elif exit: - print("error: unable to run `{}`: {}".format(' '.join(cmd), exc), file=sys.stderr) - print("Please make sure it's installed and in the path.", file=sys.stderr) + eprint("error: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("Please make sure it's installed and in the path.") sys.exit(1) return None @@ -239,14 +243,12 @@ def default_build_triple(verbose): host = next(x for x in version.split('\n') if x.startswith("host: ")) triple = host.split("host: ")[1] if verbose: - print("detected default triple {} from pre-installed rustc".format(triple), - file=sys.stderr) + eprint("detected default triple {} from pre-installed rustc".format(triple)) return triple except Exception as e: if verbose: - print("pre-installed rustc not detected: {}".format(e), - file=sys.stderr) - print("falling back to auto-detect", file=sys.stderr) + eprint("pre-installed rustc not detected: {}".format(e)) + eprint("falling back to auto-detect") required = not platform_is_win32() uname = require(["uname", "-smp"], exit=required) @@ -672,15 +674,14 @@ def get_answer(): if not is_nixos: in_nix_shell = os.getenv('IN_NIX_SHELL') if in_nix_shell: - print("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), - "you may need to set `patch-binaries-for-nix=true` in config.toml", - file=sys.stderr) + eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), + "you may need to set `patch-binaries-for-nix=true` in config.toml") return is_nixos answer = self._should_fix_bins_and_dylibs = get_answer() if answer: - print("info: You seem to be using Nix.", file=sys.stderr) + eprint("info: You seem to be using Nix.") return answer def fix_bin_or_dylib(self, fname): @@ -693,7 +694,7 @@ def fix_bin_or_dylib(self, fname): Please see https://nixos.org/patchelf.html for more information """ assert self._should_fix_bins_and_dylibs is True - print("attempting to patch", fname, file=sys.stderr) + eprint("attempting to patch", fname) # Only build `.nix-deps` once. nix_deps_dir = self.nix_deps_dir @@ -726,7 +727,7 @@ def fix_bin_or_dylib(self, fname): "nix-build", "-E", nix_expr, "-o", nix_deps_dir, ]) except subprocess.CalledProcessError as reason: - print("warning: failed to call nix-build:", reason, file=sys.stderr) + eprint("warning: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir @@ -746,7 +747,7 @@ def fix_bin_or_dylib(self, fname): try: subprocess.check_output([patchelf] + patchelf_args + [fname]) except subprocess.CalledProcessError as reason: - print("warning: failed to call patchelf:", reason, file=sys.stderr) + eprint("warning: failed to call patchelf:", reason) return def rustc_stamp(self): @@ -888,7 +889,7 @@ def build_bootstrap(self): if "GITHUB_ACTIONS" in env: print("::group::Building bootstrap") else: - print("Building bootstrap", file=sys.stderr) + eprint("Building bootstrap") args = self.build_bootstrap_cmd(env) # Run this from the source directory so cargo finds .cargo/config @@ -997,12 +998,9 @@ def check_vendored_status(self): if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - print('info: looks like you\'re trying to run this command as root', - file=sys.stderr) - print(' and so in order to preserve your $HOME this will now', - file=sys.stderr) - print(' use vendored sources by default.', - file=sys.stderr) + eprint('info: looks like you\'re trying to run this command as root') + eprint(' and so in order to preserve your $HOME this will now') + eprint(' use vendored sources by default.') cargo_dir = os.path.join(self.rust_root, '.cargo') if self.use_vendored_sources: @@ -1012,18 +1010,14 @@ def check_vendored_status(self): "--sync ./src/tools/rust-analyzer/Cargo.toml " \ "--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \ "--sync ./src/bootstrap/Cargo.toml " - print('error: vendoring required, but vendor directory does not exist.', - file=sys.stderr) - print(' Run `cargo vendor {}` to initialize the ' - 'vendor directory.'.format(sync_dirs), - file=sys.stderr) - print('Alternatively, use the pre-vendored `rustc-src` dist component.', - file=sys.stderr) + eprint('error: vendoring required, but vendor directory does not exist.') + eprint(' Run `cargo vendor {}` to initialize the ' + 'vendor directory.'.format(sync_dirs)) + eprint('Alternatively, use the pre-vendored `rustc-src` dist component.') raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - print('error: vendoring required, but .cargo/config does not exist.', - file=sys.stderr) + eprint('error: vendoring required, but .cargo/config does not exist.') raise Exception("{} not found".format(cargo_dir)) else: if os.path.exists(cargo_dir): @@ -1117,10 +1111,9 @@ def main(): # If the user is asking for help, let them know that the whole download-and-build # process has to happen before anything is printed out. if help_triggered: - print( + eprint( "info: Downloading and building bootstrap before processing --help command.\n" - " See src/bootstrap/README.md for help with common commands." - , file=sys.stderr) + " See src/bootstrap/README.md for help with common commands.") exit_code = 0 success_word = "successfully" @@ -1131,12 +1124,11 @@ def main(): exit_code = error.code else: exit_code = 1 - print(error, file=sys.stderr) + eprint(error) success_word = "unsuccessfully" if not help_triggered: - print("Build completed", success_word, "in", format_build_time(time() - start_time), - file=sys.stderr) + eprint("Build completed", success_word, "in", format_build_time(time() - start_time)) sys.exit(exit_code) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index b62aa9992469b..85cd8abb99550 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -45,6 +45,23 @@ fn sanitize_sh(path: &Path) -> String { } } +fn is_dir_writable_for_user(dir: &PathBuf) -> bool { + let tmp_file = dir.join(".tmp"); + match fs::File::create(&tmp_file) { + Ok(_) => { + fs::remove_file(tmp_file).unwrap(); + true + } + Err(e) => { + if e.kind() == std::io::ErrorKind::PermissionDenied { + false + } else { + panic!("Failed the write access check for the current user. {}", e); + } + } + } +} + fn install_sh( builder: &Builder<'_>, package: &str, @@ -56,6 +73,17 @@ fn install_sh( let prefix = default_path(&builder.config.prefix, "/usr/local"); let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); + + // Sanity check for the user write access on prefix and sysconfdir + assert!( + is_dir_writable_for_user(&prefix), + "User doesn't have write access on `install.prefix` path in the `config.toml`.", + ); + assert!( + is_dir_writable_for_user(&sysconfdir), + "User doesn't have write access on `install.sysconfdir` path in `config.toml`." + ); + let datadir = prefix.join(default_path(&builder.config.datadir, "share")); let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust")); let mandir = prefix.join(default_path(&builder.config.mandir, "share/man")); @@ -92,6 +120,9 @@ fn prepare_dir(mut path: PathBuf) -> String { // More information on the environment variable is available here: // https://www.gnu.org/prep/standards/html_node/DESTDIR.html if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) { + // Sanity check for the user write access on DESTDIR + assert!(is_dir_writable_for_user(&destdir), "User doesn't have write access on DESTDIR."); + let without_destdir = path.clone(); path = destdir; // Custom .join() which ignores disk roots. diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index b83b198780ba7..2e64568371306 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -271,7 +271,7 @@ For targets: `loongarch64-unknown-linux-gnu` - Operating System > Linux kernel version = 5.19.16 - Binary utilities > Version of binutils = 2.40 - C-library > glibc version = 2.36 -- C compiler > gcc version = 13.1.0 +- C compiler > gcc version = 13.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `mips-linux-gnu.defconfig` @@ -407,7 +407,7 @@ For targets: `riscv64-unknown-linux-gnu` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 4.20.17 -- Binary utilities > Version of binutils = 2.32 +- Binary utilities > Version of binutils = 2.36.1 - C-library > glibc version = 2.29 - C compiler > gcc version = 8.5.0 - C compiler > C++ = ENABLE -- to cross compile LLVM diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 78689c429c2e3..55c737bd0aa31 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -3,9 +3,8 @@ FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -# The latest released version does not support LoongArch. -COPY scripts/crosstool-ng-git.sh /scripts/ -RUN sh /scripts/crosstool-ng-git.sh +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 670e37b9d01a7..01b46118b9c1e 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -128,6 +128,8 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi ENV TARGETS=$TARGETS,i686-unknown-freebsd ENV TARGETS=$TARGETS,x86_64-unknown-none +ENV TARGETS=$TARGETS,loongarch64-unknown-none +ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh deleted file mode 100644 index b8d3991532717..0000000000000 --- a/src/ci/docker/scripts/crosstool-ng-git.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -set -ex - -URL=https://github.com/crosstool-ng/crosstool-ng -REV=227d99d7f3115f3a078595a580d2b307dcd23e93 - -mkdir crosstool-ng -cd crosstool-ng -git init -git fetch --depth=1 ${URL} ${REV} -git reset --hard FETCH_HEAD -./bootstrap -./configure --prefix=/usr/local -make -j$(nproc) -make install -cd .. -rm -rf crosstool-ng diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh index a28d7bde2accf..c3ee19b8d2c1f 100644 --- a/src/ci/docker/scripts/crosstool-ng.sh +++ b/src/ci/docker/scripts/crosstool-ng.sh @@ -1,7 +1,7 @@ #!/bin/sh set -ex -CT_NG=1.25.0 +CT_NG=1.26.0 url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-$CT_NG.tar.gz" curl -Lf $url | tar xzf - diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 5701b002f2185..ff831a2050480 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -157,6 +157,8 @@ target | std | notes `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI +[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) +[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL @@ -274,8 +276,6 @@ target | std | host | notes `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | -[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) -[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index d0ae3425fa8eb..68d7c9d85e444 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -1,6 +1,6 @@ # `loongarch*-unknown-none*` -**Tier: 3** +**Tier: 2** Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc. diff --git a/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md new file mode 100644 index 0000000000000..a1fcb631c6826 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md @@ -0,0 +1,8 @@ +# `link-native-libraries` + +This option allows ignoring libraries specified in `#[link]` attributes instead of passing them to the linker. +This can be useful in build systems that manage native libraries themselves and pass them manually, +e.g. with `-Clink-arg`. + +- `yes` - Pass native libraries to the linker. Default. +- `no` - Don't pass native libraries to the linker. diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 1fade6ce95b89..189cc910a8d75 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -43,14 +43,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc_ast::ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); @@ -58,9 +58,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.lint(TEST_LINT, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 34d81f51f76e6..5a1612e76e306 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1183,7 +1183,13 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( // but shouldn't change any code meaning. let mut output = clean_middle_ty(sig.output(), cx, None, None); - if let Some(did) = did && cx.tcx.asyncness(did).is_async() { + // If the return type isn't an `impl Trait`, we can safely assume that this + // function isn't async without needing to execute the query `asyncness` at + // all which gives us a noticeable performance boost. + if let Some(did) = did + && let Type::ImplTrait(_) = output + && cx.tcx.asyncness(did).is_async() + { output = output.sugared_async_return_type(); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f5251f50b7a7b..1d8fa2e636edd 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1604,14 +1604,16 @@ impl Type { /// /// This function will panic if the return type does not match the expected sugaring for async /// functions. - pub(crate) fn sugared_async_return_type(&self) -> Type { - if let Type::ImplTrait(v) = self && - let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..] + pub(crate) fn sugared_async_return_type(self) -> Type { + if let Type::ImplTrait(mut v) = self + && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _ )) = v.pop() + && let Some(segment) = trait_.segments.pop() + && let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args + && let Some(binding) = bindings.pop() + && let TypeBindingKind::Equality { term } = binding.kind + && let Term::Type(ty) = term { - let bindings = trait_.bindings().unwrap(); - let ret_ty = bindings[0].term(); - let ty = ret_ty.ty().expect("unexpected constant in async fn return term"); - ty.clone() + ty } else { panic!("unexpected async fn return type") } @@ -2189,16 +2191,6 @@ impl Path { } }) } - - pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> { - self.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { - Some(&**bindings) - } else { - None - } - }) - } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -2478,15 +2470,6 @@ pub(crate) enum TypeBindingKind { Constraint { bounds: Vec }, } -impl TypeBinding { - pub(crate) fn term(&self) -> &Term { - match self.kind { - TypeBindingKind::Equality { ref term } => term, - _ => panic!("expected equality type binding for parenthesized generic args"), - } - } -} - /// The type, lifetime, or constant that a private type alias's parameter should be /// replaced with when expanding a use of that type alias. /// diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 24597c3aca312..741d329fb1922 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -681,7 +681,7 @@ pub(crate) fn make_test( if s.contains(crate_name) { // rustdoc implicitly inserts an `extern crate` item for the own crate // which may be unused, so we need to allow the lint. - prog.push_str(&format!("#[allow(unused_extern_crates)]\n")); + prog.push_str("#[allow(unused_extern_crates)]\n"); prog.push_str(&format!("extern crate r#{crate_name};\n")); line_offset += 1; diff --git a/src/llvm-project b/src/llvm-project index 42263494d29fe..d404cba4e39df 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 42263494d29febc26d3c1ebdaa7b63677573ec47 +Subproject commit d404cba4e39df595710869988ded7cbe1104b52f diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 0f7a3c2f952ad..5153dd26f4ad4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -98,6 +98,8 @@ static TARGETS: &[&str] = &[ "i686-unknown-linux-musl", "i686-unknown-uefi", "loongarch64-unknown-linux-gnu", + "loongarch64-unknown-none", + "loongarch64-unknown-none-softfloat", "m68k-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2", "mips-unknown-linux-gnu", diff --git a/src/tools/cargo b/src/tools/cargo index e6aabe8b3fcf6..59596f0f31a94 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit e6aabe8b3fcf639be3a5bf68e77853bd7b3fa27d +Subproject commit 59596f0f31a94fde48b5aa7e945cd0b7ceca9620 diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index 2895595e03908..8a7e487466610 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub NEEDLESS_RAW_STRING_HASHES, - style, + pedantic, "suggests reducing the number of hashes around a raw string literal" } impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]); 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 87380f14f9a4d..bbb5ade8b9f36 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 @@ -28,8 +28,8 @@ declare_clippy_lint! { /// know the name of the lint. /// /// ### Known problems - /// Only checks for lints associated using the - /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros. + /// Only checks for lints associated using the `declare_lint_pass!` and + /// `impl_lint_pass!` macros. /// /// ### Example /// ```rust,ignore diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index f04467dc19d37..9dbb4c68d13f8 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -30,20 +30,26 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - locals.len() ]; - traversal::ReversePostorder::new(mir, location.block).try_fold(init, |usage, (tbb, tdata)| { - // Give up on loops - if tdata.terminator().successors().any(|s| s == location.block) { - return None; - } + traversal::Postorder::new(&mir.basic_blocks, location.block) + .collect::>() + .into_iter() + .rev() + .try_fold(init, |usage, tbb| { + let tdata = &mir.basic_blocks[tbb]; + + // Give up on loops + if tdata.terminator().successors().any(|s| s == location.block) { + return None; + } - let mut v = V { - locals, - location, - results: usage, - }; - v.visit_basic_block_data(tbb, tdata); - Some(v.results) - }) + let mut v = V { + locals, + location, + results: usage, + }; + v.visit_basic_block_data(tbb, tdata); + Some(v.results) + }) } struct V<'a> { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index ba273489eb8af..0e1bf0c6c2dce 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -580,6 +580,8 @@ pub struct TargetCfg { pub(crate) sanitizers: Vec, #[serde(rename = "supports-xray", default)] pub(crate) xray: bool, + #[serde(default = "default_reloc_model")] + pub(crate) relocation_model: String, } impl TargetCfg { @@ -592,6 +594,10 @@ fn default_os() -> String { "none".into() } +fn default_reloc_model() -> String { + "pic".into() +} + #[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)] #[serde(rename_all = "kebab-case")] pub enum Endian { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 1113721fff612..2b7a4387cebc1 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -134,6 +134,11 @@ pub(super) fn handle_needs( condition: config.target_cfg().dynamic_linking, ignore_reason: "ignored on targets without dynamic linking", }, + Need { + name: "needs-relocation-model-pic", + condition: config.target_cfg().relocation_model == "pic", + ignore_reason: "ignored on targets without PIC relocation model", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index 23e88844bd0b8..9821677a1226e 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.49" +version = "0.51.1" diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index 91d981462e816..dff2c5e467afa 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -1,5 +1,7 @@ +use std::env; +use std::error::Error; use std::fs; -use std::io::{self, Write}; +use std::io::{self, Read, Seek, Write}; use std::path::PathBuf; /// This is printed to the file before the rest of the contents. @@ -11,25 +13,20 @@ const PRELUDE: &str = r#"// This file is autogenerated. // ignore-tidy-filelength "#; -fn main() -> io::Result<()> { +fn main() -> Result<(), Box> { let mut path: PathBuf = - std::env::args_os().nth(1).expect("a path to the rust repository is required").into(); - path.push("library/std/src/sys/windows/c/windows_sys.lst"); + env::args_os().nth(1).expect("a path to the rust repository is required").into(); + path.push("library/std/src/sys/windows/c"); + env::set_current_dir(&path)?; - // Load the list of APIs - let buffer = fs::read_to_string(&path)?; - let names: Vec<&str> = buffer - .lines() - .filter_map(|line| { - let line = line.trim(); - if line.is_empty() || line.starts_with("//") { None } else { Some(line) } - }) - .collect(); + let info = windows_bindgen::bindgen(["--etc", "windows_sys.lst"])?; + println!("{info}"); - // Write the bindings to windows-sys.rs - let bindings = windows_bindgen::standalone_std(&names); - path.set_extension("rs"); - let mut f = std::fs::File::create(&path)?; + // add some gunk to the output file. + let mut f = fs::File::options().read(true).write(true).open("windows_sys.rs")?; + let mut bindings = String::new(); + f.read_to_string(&mut bindings)?; + f.seek(io::SeekFrom::Start(0))?; f.write_all(PRELUDE.as_bytes())?; f.write_all(bindings.as_bytes())?; diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 07dd52ce94159..b60de8344d948 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2ba4eb2d49e774b5fbc2a06258ac7b0f60b92b7e +bb6c66be3793ac5c738eeac91ecdc4b99388d0b4 diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index a9cf4bb0e23eb..8c90ceba1e4aa 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -60,7 +60,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // The rest jumps to `ret` immediately. - this.emulate_intrinsic_by_name(intrinsic_name, args, dest)?; + this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?; trace!("{:?}", this.dump_place(dest)); this.go_to_block(ret); @@ -71,6 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_intrinsic_by_name( &mut self, intrinsic_name: &str, + generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { @@ -80,7 +81,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return this.emulate_atomic_intrinsic(name, args, dest); } if let Some(name) = intrinsic_name.strip_prefix("simd_") { - return this.emulate_simd_intrinsic(name, args, dest); + return this.emulate_simd_intrinsic(name, generic_args, args, dest); } match intrinsic_name { diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index de0c58de44fd1..200f37efa27b1 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -12,6 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_simd_intrinsic( &mut self, intrinsic_name: &str, + generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { @@ -488,6 +489,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_immediate(*val, &dest)?; } } + "shuffle_generic" => { + let [left, right] = check_arg_count(args)?; + let (left, left_len) = this.operand_to_simd(left)?; + let (right, right_len) = this.operand_to_simd(right)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + let index = generic_args[2] + .expect_const() + .eval(*this.tcx, this.param_env(), Some(this.tcx.span)) + .unwrap() + .unwrap_branch(); + let index_len = index.len(); + + assert_eq!(left_len, right_len); + assert_eq!(index_len as u64, dest_len); + + for i in 0..dest_len { + let src_index: u64 = index[usize::try_from(i).unwrap()] + .unwrap_leaf() + .try_to_u32() + .unwrap() + .into(); + let dest = this.project_index(&dest, i)?; + + let val = if src_index < left_len { + this.read_immediate(&this.project_index(&left, src_index)?)? + } else if src_index < left_len.checked_add(right_len).unwrap() { + let right_idx = src_index.checked_sub(left_len).unwrap(); + this.read_immediate(&this.project_index(&right, right_idx)?)? + } else { + span_bug!( + this.cur_span(), + "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}", + ); + }; + this.write_immediate(*val, &dest)?; + } + } "shuffle" => { let [left, right, index] = check_arg_count(args)?; let (left, left_len) = this.operand_to_simd(left)?; diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index ee67a65a4f9a2..969162e2c1e9e 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -1,5 +1,6 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(portable_simd, platform_intrinsics)] +#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)] +#![allow(incomplete_features)] use std::simd::*; extern "platform-intrinsic" { @@ -390,6 +391,8 @@ fn simd_intrinsics() { fn simd_reduce_any(x: T) -> bool; fn simd_reduce_all(x: T) -> bool; fn simd_select(m: M, yes: T, no: T) -> T; + fn simd_shuffle_generic(x: T, y: T) -> U; + fn simd_shuffle(x: T, y: T, idx: IDX) -> U; } unsafe { // Make sure simd_eq returns all-1 for `true` @@ -413,6 +416,16 @@ fn simd_intrinsics() { simd_select(i8x4::from_array([0, -1, -1, 0]), b, a), i32x4::from_array([10, 2, 10, 10]) ); + assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); + assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3, 1, 0, 2] }), a,); + assert_eq!( + simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b), + i32x4::from_array([4, 2, 1, 10]), + ); + assert_eq!( + simd_shuffle::<_, _, i32x4>(a, b, const { [7, 5, 4, 6] }), + i32x4::from_array([4, 2, 1, 10]), + ); } } diff --git a/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs index f518266016e09..b9f74340472c0 100644 --- a/tests/incremental/change_crate_dep_kind.rs +++ b/tests/incremental/change_crate_dep_kind.rs @@ -5,6 +5,7 @@ // needs-unwind // revisions:cfail1 cfail2 // compile-flags: -Z query-dep-graph -Cpanic=unwind +// needs-unwind // build-pass (FIXME(62277): could be check-pass?) #![feature(panic_unwind)] diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 182ca7d926c6b..23b81705f9aa0 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -302,7 +302,7 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index 4d3baee7f117f..15330b13cc214 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -2,13 +2,16 @@ /* generator_layout = GeneratorLayout { field_tys: { _0: GeneratorSavedTy { - ty: Alias( - Opaque, - AliasTy { - args: [ - ], - def_id: DefId(0:7 ~ async_await[ccf8]::a::{opaque#0}), - }, + ty: Generator( + DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + [ + std::future::ResumeTy, + (), + (), + GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), + (), + ], + Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:15:9: 15:14 (#8), @@ -17,13 +20,16 @@ ignore_for_traits: false, }, _1: GeneratorSavedTy { - ty: Alias( - Opaque, - AliasTy { - args: [ - ], - def_id: DefId(0:7 ~ async_await[ccf8]::a::{opaque#0}), - }, + ty: Generator( + DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + [ + std::future::ResumeTy, + (), + (), + GeneratorWitness(DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), []), + (), + ], + Static, ), source_info: SourceInfo { span: $DIR/async_await.rs:16:9: 16:14 (#10), @@ -49,15 +55,15 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, debug _task_context => _38; let mut _0: std::task::Poll<()>; let _3: (); - let mut _4: impl std::future::Future; - let mut _5: impl std::future::Future; - let mut _6: impl std::future::Future; + let mut _4: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _5: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _6: {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _7: (); let _8: (); let mut _9: std::task::Poll<()>; - let mut _10: std::pin::Pin<&mut impl std::future::Future>; - let mut _11: &mut impl std::future::Future; - let mut _12: &mut impl std::future::Future; + let mut _10: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>; + let mut _11: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _12: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _13: &mut std::task::Context<'_>; let mut _14: &mut std::task::Context<'_>; let mut _15: &mut std::task::Context<'_>; @@ -65,14 +71,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, let mut _18: !; let mut _19: &mut std::task::Context<'_>; let mut _20: (); - let mut _21: impl std::future::Future; - let mut _22: impl std::future::Future; - let mut _23: impl std::future::Future; + let mut _21: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _22: {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _23: {async fn body@$DIR/async_await.rs:11:14: 11:16}; let _24: (); let mut _25: std::task::Poll<()>; - let mut _26: std::pin::Pin<&mut impl std::future::Future>; - let mut _27: &mut impl std::future::Future; - let mut _28: &mut impl std::future::Future; + let mut _26: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>; + let mut _27: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; + let mut _28: &mut {async fn body@$DIR/async_await.rs:11:14: 11:16}; let mut _29: &mut std::task::Context<'_>; let mut _30: &mut std::task::Context<'_>; let mut _31: &mut std::task::Context<'_>; @@ -84,7 +90,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, let mut _38: &mut std::task::Context<'_>; let mut _39: u32; scope 1 { - debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: impl std::future::Future); + debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); let _17: (); scope 2 { } @@ -93,7 +99,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, } } scope 4 { - debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: impl std::future::Future); + debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); let _33: (); scope 5 { } @@ -116,13 +122,13 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, } bb2: { - _4 = as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; + _4 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; } bb3: { StorageDead(_5); nop; - (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: impl std::future::Future) = move _4; + (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}) = move _4; goto -> bb4; } @@ -132,9 +138,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: impl std::future::Future); + _12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); _11 = &mut (*_12); - _10 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; + _10 = Pin::<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; } bb5: { @@ -150,7 +156,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, bb6: { _13 = &mut (*_14); StorageDead(_15); - _9 = as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; + _9 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; } bb7: { @@ -187,7 +193,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, StorageDead(_12); StorageDead(_9); StorageDead(_8); - drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: impl std::future::Future)) -> [return: bb12, unwind unreachable]; + drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:11:14: 11:16})) -> [return: bb12, unwind unreachable]; } bb11: { @@ -212,13 +218,13 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, } bb14: { - _21 = as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + _21 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; } bb15: { StorageDead(_22); nop; - (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: impl std::future::Future) = move _21; + (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}) = move _21; goto -> bb16; } @@ -228,9 +234,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: impl std::future::Future); + _28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16}); _27 = &mut (*_28); - _26 = Pin::<&mut impl Future>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; + _26 = Pin::<&mut {async fn body@$DIR/async_await.rs:11:14: 11:16}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; } bb17: { @@ -246,7 +252,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, bb18: { _29 = &mut (*_30); StorageDead(_31); - _25 = as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; + _25 = <{async fn body@$DIR/async_await.rs:11:14: 11:16} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; } bb19: { @@ -279,7 +285,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:14:18: 17:2}>, StorageDead(_28); StorageDead(_25); StorageDead(_24); - drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: impl std::future::Future)) -> [return: bb23, unwind unreachable]; + drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:14:18: 17:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:11:14: 11:16})) -> [return: bb23, unwind unreachable]; } bb22: { diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff index c94dd2556956c..b532b133a83a5 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-abort.diff @@ -15,28 +15,44 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind unreachable]; + _4 = hide_foo() -> [return: bb1, unwind: bb6]; } bb1: { _3 = &_4; StorageLive(_5); _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; } bb2: { StorageDead(_5); StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; + drop(_1) -> [return: bb4, unwind: bb7]; } - bb3: { + bb4: { return; } + + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + resume; + } } diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff index cbfb39115b370..bcebcf297c2b1 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff @@ -15,35 +15,43 @@ StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = hide_foo() -> [return: bb1, unwind: bb4]; + _4 = hide_foo() -> [return: bb1, unwind: bb6]; } bb1: { _3 = &_4; StorageLive(_5); _5 = (); -- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; -+ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; +- _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; ++ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb5]; } bb2: { StorageDead(_5); StorageDead(_3); + drop(_4) -> [return: bb3, unwind: bb6]; + } + + bb3: { StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind: bb5]; + drop(_1) -> [return: bb4, unwind continue]; } - bb3: { + bb4: { return; } - bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate(cleanup)]; + bb5 (cleanup): { + drop(_4) -> [return: bb6, unwind terminate(cleanup)]; } - bb5 (cleanup): { + bb6 (cleanup): { + drop(_1) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { resume; } } diff --git a/tests/mir-opt/ssa_unreachable_116212.rs b/tests/mir-opt/ssa_unreachable_116212.rs new file mode 100644 index 0000000000000..f588665876c87 --- /dev/null +++ b/tests/mir-opt/ssa_unreachable_116212.rs @@ -0,0 +1,14 @@ +// Regression test for issue #116212. + +#![feature(never_type)] + +use std::mem::MaybeUninit; + +struct Foo { + x: u8, + y: !, +} + +fn main() { + let foo = unsafe { MaybeUninit::::uninit().assume_init() }; +} diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile index 1f2812cb08792..9ba077b18547e 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile @@ -3,7 +3,7 @@ include ../tools.mk # ignore-cross-compile # only-linux -# Make sure -Zpacked_bundled_libs-like behavior activates with whole-archive. +# Make sure -Zpacked_bundled_libs-like behavior activates with +bundle,+whole-archive. # We're using the llvm-nm instead of the system nm to ensure it is compatible # with the LLVM bitcode generated by rustc. @@ -11,7 +11,7 @@ NM = "$(LLVM_BIN_DIR)"/llvm-nm all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) $(call NATIVE_STATICLIB,native_dep_4) # test cfg with packed bundle - $(RUSTC) rust_dep_cfg.rs --crate-type=rlib -Zpacked_bundled_libs + $(RUSTC) rust_dep_cfg.rs --crate-type=rlib $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep_cfg.rlib --crate-type=staticlib --cfg should_add $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_1.a" $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_2.a" diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs index abd846b6862d1..bde9b739de6a3 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs @@ -1,5 +1,3 @@ -#![feature(packed_bundled_libs)] - #[link(name = "native_dep_1", kind = "static", modifiers = "+whole-archive,+bundle")] extern "C" {} diff --git a/tests/rustdoc/issue-15169.rs b/tests/rustdoc/anchor-id-trait-method-15169.rs similarity index 56% rename from tests/rustdoc/issue-15169.rs rename to tests/rustdoc/anchor-id-trait-method-15169.rs index e525d85e21ec0..26bb59c1875fd 100644 --- a/tests/rustdoc/issue-15169.rs +++ b/tests/rustdoc/anchor-id-trait-method-15169.rs @@ -1,3 +1,7 @@ // @has issue_15169/struct.Foo.html '//*[@id="method.eq"]' 'fn eq' + +// https://github.com/rust-lang/rust/issues/15169 +#![crate_name="issue_15169"] + #[derive(PartialEq)] pub struct Foo; diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/assoc-type-bindings-20646.rs similarity index 90% rename from tests/rustdoc/issue-20646.rs rename to tests/rustdoc/assoc-type-bindings-20646.rs index b2ee9c26014b3..375b5b5b23ea5 100644 --- a/tests/rustdoc/issue-20646.rs +++ b/tests/rustdoc/assoc-type-bindings-20646.rs @@ -1,6 +1,8 @@ // aux-build:issue-20646.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20646 +#![crate_name="issue_20646"] #![feature(associated_types)] extern crate issue_20646; diff --git a/tests/rustdoc/issue-19190-2.rs b/tests/rustdoc/deref-methods-19190-foreign-type.rs similarity index 77% rename from tests/rustdoc/issue-19190-2.rs rename to tests/rustdoc/deref-methods-19190-foreign-type.rs index b6416e2e5b97e..c8326992115c7 100644 --- a/tests/rustdoc/issue-19190-2.rs +++ b/tests/rustdoc/deref-methods-19190-foreign-type.rs @@ -1,3 +1,7 @@ +// https://github.com/rust-lang/rust/issues/19190 + +#![crate_name="issue_19190_2"] + use std::ops::Deref; pub struct Bar; diff --git a/tests/rustdoc/issue-19190-3.rs b/tests/rustdoc/deref-methods-19190-inline.rs similarity index 90% rename from tests/rustdoc/issue-19190-3.rs rename to tests/rustdoc/deref-methods-19190-inline.rs index 4d34ce6509fe3..619b268d68b39 100644 --- a/tests/rustdoc/issue-19190-3.rs +++ b/tests/rustdoc/deref-methods-19190-inline.rs @@ -1,6 +1,9 @@ // aux-build:issue-19190-3.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/19190 +#![crate_name="issue_19190_3"] + extern crate issue_19190_3; use std::ops::Deref; diff --git a/tests/rustdoc/issue-19190.rs b/tests/rustdoc/deref-methods-19190.rs similarity index 86% rename from tests/rustdoc/issue-19190.rs rename to tests/rustdoc/deref-methods-19190.rs index 2046273e2c1ba..4c274d82ff785 100644 --- a/tests/rustdoc/issue-19190.rs +++ b/tests/rustdoc/deref-methods-19190.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/19190 +#![crate_name="issue_19190"] + use std::ops::Deref; pub struct Foo; diff --git a/tests/rustdoc/issue-13698.rs b/tests/rustdoc/doc-hidden-method-13698.rs similarity index 81% rename from tests/rustdoc/issue-13698.rs rename to tests/rustdoc/doc-hidden-method-13698.rs index 3046a8a28627d..f1bd6e73babdd 100644 --- a/tests/rustdoc/issue-13698.rs +++ b/tests/rustdoc/doc-hidden-method-13698.rs @@ -1,6 +1,9 @@ // aux-build:issue-13698.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/13698 +#![crate_name="issue_13698"] + extern crate issue_13698; pub struct Foo; diff --git a/tests/rustdoc/issue-18199.rs b/tests/rustdoc/doc-test-attr-18199.rs similarity index 79% rename from tests/rustdoc/issue-18199.rs rename to tests/rustdoc/doc-test-attr-18199.rs index 9cc58b162f37e..c9d2235321c87 100644 --- a/tests/rustdoc/issue-18199.rs +++ b/tests/rustdoc/doc-test-attr-18199.rs @@ -1,4 +1,5 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/18199 #![doc(test(attr(feature(staged_api))))] diff --git a/tests/rustdoc/issue-15347.rs b/tests/rustdoc/document-hidden-items-15347.rs similarity index 61% rename from tests/rustdoc/issue-15347.rs rename to tests/rustdoc/document-hidden-items-15347.rs index e93d74011681b..d8a760e566602 100644 --- a/tests/rustdoc/issue-15347.rs +++ b/tests/rustdoc/document-hidden-items-15347.rs @@ -1,4 +1,7 @@ // compile-flags: -Z unstable-options --document-hidden-items +// https://github.com/rust-lang/rust/issues/15347 + +#![crate_name="issue_15347"] // @has issue_15347/fn.foo.html #[doc(hidden)] diff --git a/tests/rustdoc/issue-12834.rs b/tests/rustdoc/highlight-invalid-rust-12834.rs similarity index 80% rename from tests/rustdoc/issue-12834.rs rename to tests/rustdoc/highlight-invalid-rust-12834.rs index 9605a1e78c105..f8acc5002648f 100644 --- a/tests/rustdoc/issue-12834.rs +++ b/tests/rustdoc/highlight-invalid-rust-12834.rs @@ -1,6 +1,8 @@ // Tests that failing to syntax highlight a rust code-block doesn't cause // rustdoc to fail, while still rendering the code-block (without highlighting). +// https://github.com/rust-lang/rust/issues/12834 +#![crate_name="issue_12834"] #![allow(rustdoc::invalid_rust_codeblocks)] // @has issue_12834/fn.foo.html diff --git a/tests/rustdoc/issue-19181.rs b/tests/rustdoc/ice-type-error-19181.rs similarity index 68% rename from tests/rustdoc/issue-19181.rs rename to tests/rustdoc/ice-type-error-19181.rs index 3dea152fc6ecb..3ced613666406 100644 --- a/tests/rustdoc/issue-19181.rs +++ b/tests/rustdoc/ice-type-error-19181.rs @@ -1,4 +1,5 @@ // compile-flags:--test +// https://github.com/rust-lang/rust/issues/19181 // rustdoc should not panic when target crate has compilation errors diff --git a/tests/rustdoc/issue-20175.rs b/tests/rustdoc/impl-ref-20175.rs similarity index 68% rename from tests/rustdoc/issue-20175.rs rename to tests/rustdoc/impl-ref-20175.rs index 6a42e2afbf43c..a92db2d0a665b 100644 --- a/tests/rustdoc/issue-20175.rs +++ b/tests/rustdoc/impl-ref-20175.rs @@ -1,3 +1,7 @@ +// https://github.com/rust-lang/rust/issues/20175 + +#![crate_name="issue_20175"] + pub trait Foo { fn foo(&self) {} } diff --git a/tests/rustdoc/issue-16265-1.rs b/tests/rustdoc/infinite-redirection-16265-1.rs similarity index 71% rename from tests/rustdoc/issue-16265-1.rs rename to tests/rustdoc/infinite-redirection-16265-1.rs index 2fda637a64131..7d72469bd72c7 100644 --- a/tests/rustdoc/issue-16265-1.rs +++ b/tests/rustdoc/infinite-redirection-16265-1.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/16265 +#![crate_name="issue_16265_1"] + pub struct Foo; // @hasraw issue_16265_1/traits/index.html 'source' diff --git a/tests/rustdoc/issue-16265-2.rs b/tests/rustdoc/infinite-redirection-16265-2.rs similarity index 50% rename from tests/rustdoc/issue-16265-2.rs rename to tests/rustdoc/infinite-redirection-16265-2.rs index c3eb356171e85..7a4791c5fd487 100644 --- a/tests/rustdoc/issue-16265-2.rs +++ b/tests/rustdoc/infinite-redirection-16265-2.rs @@ -1,3 +1,6 @@ +// https://github.com/rust-lang/rust/issues/16265 +#![crate_name="issue_16265_2"] + // @hasraw issue_16265_2/index.html 'source' trait Y {} diff --git a/tests/rustdoc/issue-20727-2.rs b/tests/rustdoc/inline-assoc-type-20727-bindings.rs similarity index 90% rename from tests/rustdoc/issue-20727-2.rs rename to tests/rustdoc/inline-assoc-type-20727-bindings.rs index c1aa9617b2e25..e59dec29d030a 100644 --- a/tests/rustdoc/issue-20727-2.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bindings.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_2"] + extern crate issue_20727; // @has issue_20727_2/trait.Add.html diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs similarity index 90% rename from tests/rustdoc/issue-20727-3.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs index 2f9d91fc5f724..005ee3e329416 100644 --- a/tests/rustdoc/issue-20727-3.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds-deref.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_3"] + extern crate issue_20727; pub trait Bar {} diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/inline-assoc-type-20727-bounds-index.rs similarity index 95% rename from tests/rustdoc/issue-20727-4.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds-index.rs index ec9f18fc3feb8..1a3f4cd20c1e2 100644 --- a/tests/rustdoc/issue-20727-4.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds-index.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727_4"] + extern crate issue_20727; // @has issue_20727_4/trait.Index.html diff --git a/tests/rustdoc/issue-20727.rs b/tests/rustdoc/inline-assoc-type-20727-bounds.rs similarity index 90% rename from tests/rustdoc/issue-20727.rs rename to tests/rustdoc/inline-assoc-type-20727-bounds.rs index 266848beef93d..7cbc8d38107db 100644 --- a/tests/rustdoc/issue-20727.rs +++ b/tests/rustdoc/inline-assoc-type-20727-bounds.rs @@ -1,6 +1,9 @@ // aux-build:issue-20727.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/20727 +#![crate_name="issue_20727"] + extern crate issue_20727; // @has issue_20727/trait.Deref.html diff --git a/tests/rustdoc/issue-16019.rs b/tests/rustdoc/macro-ice-16019.rs similarity index 75% rename from tests/rustdoc/issue-16019.rs rename to tests/rustdoc/macro-ice-16019.rs index 239d92378d9bb..d0f82e0a314ce 100644 --- a/tests/rustdoc/issue-16019.rs +++ b/tests/rustdoc/macro-ice-16019.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/16019 + macro_rules! define_struct { ($rounds:expr) => ( struct Struct { diff --git a/tests/rustdoc/issue-17476.rs b/tests/rustdoc/method-link-foreign-trait-impl-17476.rs similarity index 76% rename from tests/rustdoc/issue-17476.rs rename to tests/rustdoc/method-link-foreign-trait-impl-17476.rs index a5b484c985fff..e52ab6f38c2a5 100644 --- a/tests/rustdoc/issue-17476.rs +++ b/tests/rustdoc/method-link-foreign-trait-impl-17476.rs @@ -1,5 +1,8 @@ // aux-build:issue-17476.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/17476 + +#![crate_name="issue_17476"] extern crate issue_17476; diff --git a/tests/rustdoc/issue-15318-3.rs b/tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs similarity index 61% rename from tests/rustdoc/issue-15318-3.rs rename to tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs index 2dab8f9488391..80c559756870c 100644 --- a/tests/rustdoc/issue-15318-3.rs +++ b/tests/rustdoc/primitive-raw-pointer-dox-15318-3.rs @@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/15318 +#![crate_name="issue_15318_3"] #![feature(rustc_attrs)] // @has issue_15318_3/primitive.pointer.html diff --git a/tests/rustdoc/issue-15318.rs b/tests/rustdoc/primitive-raw-pointer-link-15318.rs similarity index 76% rename from tests/rustdoc/issue-15318.rs rename to tests/rustdoc/primitive-raw-pointer-link-15318.rs index 0349fe2854c8a..77f25ff4cff08 100644 --- a/tests/rustdoc/issue-15318.rs +++ b/tests/rustdoc/primitive-raw-pointer-link-15318.rs @@ -1,6 +1,8 @@ // aux-build:issue-15318.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/15318 +#![crate_name="issue_15318"] #![no_std] extern crate issue_15318; diff --git a/tests/rustdoc/issue-15318-2.rs b/tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs similarity index 75% rename from tests/rustdoc/issue-15318-2.rs rename to tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs index 614f2c1c08e87..1b35bb185ed48 100644 --- a/tests/rustdoc/issue-15318-2.rs +++ b/tests/rustdoc/primitive-raw-pointer-link-no-inlined-15318-2.rs @@ -1,5 +1,8 @@ // aux-build:issue-15318.rs // ignore-cross-compile +// https://github.com/rust-lang/rust/issues/15318 + +#![crate_name="issue_15318_2"] #![no_std] extern crate issue_15318; diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs index f6f0c038536c8..fa6734b6c6c30 100644 --- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs +++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -6,7 +6,7 @@ extern crate rustc_middle; extern crate rustc_session; -use rustc_session::lint::{LintArray, LintPass}; +use rustc_session::lint::{LintPass, LintVec}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; declare_lint! { diff --git a/tests/ui-fulldeps/lint-pass-macros.rs b/tests/ui-fulldeps/lint-pass-macros.rs index b3c2a542792f0..4c61783418fb0 100644 --- a/tests/ui-fulldeps/lint-pass-macros.rs +++ b/tests/ui-fulldeps/lint-pass-macros.rs @@ -5,7 +5,7 @@ extern crate rustc_session; -use rustc_session::lint::{LintArray, LintPass}; +use rustc_session::lint::{LintPass, LintVec}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; declare_lint! { diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs index 4a41e7fbb72a1..150f0c6b9a2da 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-group-plugin-test.rs @@ -5,13 +5,12 @@ // Load rustc as a plugin to get macros. extern crate rustc_driver; extern crate rustc_hir; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; use rustc_driver::plugin::Registry; -use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintId, LintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext, LintId}; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs index 30956deb799ed..acc5fe76051b9 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs @@ -6,14 +6,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; +use rustc_ast::ast; use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc_ast as ast; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); diff --git a/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs index c2c024865e8a8..21de4aa7008fd 100644 --- a/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs +++ b/tests/ui-fulldeps/plugin/auxiliary/lint-tool-test.rs @@ -4,14 +4,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintId, LintPass}; use rustc_ast as ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext, LintId}; + declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); declare_tool_lint!( /// Some docs diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 249e817628303..1f049b1785a62 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -1,16 +1,174 @@ // check-pass +// revisions: host +// revisions: arm +//[arm] compile-flags: --target arm-unknown-linux-gnueabi +//[arm] needs-llvm-components: arm +// revisions: aarch64 +//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//[aarch64] needs-llvm-components: aarch64 +// revisions: s390x +//[s390x] compile-flags: --target s390x-unknown-linux-gnu +//[s390x] needs-llvm-components: systemz +// revisions: mips +//[mips] compile-flags: --target mips-unknown-linux-gnu +//[mips] needs-llvm-components: mips +// revisions: mips64 +//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +//[mips64] needs-llvm-components: mips +// revisions: sparc +//[sparc] compile-flags: --target sparc-unknown-linux-gnu +//[sparc] needs-llvm-components: sparc +// revisions: sparc64 +//[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//[sparc64] needs-llvm-components: sparc +// revisions: powerpc64 +//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//[powerpc64] needs-llvm-components: powerpc +// revisions: riscv +//[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +//[riscv] needs-llvm-components: riscv +// revisions: loongarch64 +//[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu +//[loongarch64] needs-llvm-components: loongarch +// revisions: wasm +//[wasm] compile-flags: --target wasm32-unknown-unknown +//[wasm] needs-llvm-components: webassembly +// revisions: wasi +//[wasi] compile-flags: --target wasm32-wasi +//[wasi] needs-llvm-components: webassembly +// revisions: nvptx64 +//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda +//[nvptx64] needs-llvm-components: nvptx #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] +#![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)] #![allow(unused, improper_ctypes_definitions, internal_features)] -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::num::NonZeroI32; -use std::ptr::NonNull; -// FIXME: a bunch of targets are broken in various ways. +// FIXME: some targets are broken in various ways. // Hence there are `cfg` throughout this test to disable parts of it on those targets. // sparc64: https://github.com/rust-lang/rust/issues/115336 // mips64: https://github.com/rust-lang/rust/issues/115404 +#[cfg(host)] +use std::{ + any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZeroI32, ptr::NonNull, rc::Rc, + sync::Arc, +}; + +/// To work cross-target this test must be no_core. +/// This little prelude supplies what we need. +#[cfg(not(host))] +mod prelude { + #[lang = "sized"] + pub trait Sized {} + + #[lang = "receiver"] + pub trait Receiver {} + impl Receiver for &T {} + impl Receiver for &mut T {} + + #[lang = "copy"] + pub trait Copy: Sized {} + impl Copy for i32 {} + impl Copy for f32 {} + impl Copy for &T {} + impl Copy for *const T {} + impl Copy for *mut T {} + + #[lang = "clone"] + pub trait Clone: Sized { + fn clone(&self) -> Self; + } + + #[lang = "phantom_data"] + pub struct PhantomData; + impl Copy for PhantomData {} + + #[lang = "unsafe_cell"] + #[repr(transparent)] + pub struct UnsafeCell { + value: T, + } + + pub trait Any: 'static {} + + pub enum Option { + None, + Some(T), + } + impl Copy for Option {} + + pub enum Result { + Ok(T), + Err(E), + } + impl Copy for Result {} + + #[lang = "manually_drop"] + #[repr(transparent)] + pub struct ManuallyDrop { + value: T, + } + impl Copy for ManuallyDrop {} + + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + pub struct NonNull { + pointer: *const T, + } + impl Copy for NonNull {} + + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + pub struct NonZeroI32(i32); + + // This just stands in for a non-trivial type. + pub struct Vec { + ptr: NonNull, + cap: usize, + len: usize, + } + + pub struct Unique { + pub pointer: NonNull, + pub _marker: PhantomData, + } + + pub struct Global; + + #[lang = "owned_box"] + pub struct Box(Unique, A); + + #[repr(C)] + struct RcBox { + strong: UnsafeCell, + weak: UnsafeCell, + value: T, + } + pub struct Rc { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, + } + + #[repr(C, align(8))] + struct AtomicUsize(usize); + #[repr(C)] + struct ArcInner { + strong: AtomicUsize, + weak: AtomicUsize, + data: T, + } + pub struct Arc { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, + } +} +#[cfg(not(host))] +use prelude::*; + macro_rules! assert_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { mod $name { @@ -26,8 +184,13 @@ macro_rules! assert_abi_compatible { }; } -#[derive(Copy, Clone)] struct Zst; +impl Copy for Zst {} +impl Clone for Zst { + fn clone(&self) -> Self { + Zst + } +} #[repr(C)] struct ReprC1(T); @@ -85,8 +248,8 @@ test_abi_compatible!(nonzero_int, NonZeroI32, i32); // `DispatchFromDyn` relies on ABI compatibility. // This is interesting since these types are not `repr(transparent)`. -test_abi_compatible!(rc, std::rc::Rc, *mut i32); -test_abi_compatible!(arc, std::sync::Arc, *mut i32); +test_abi_compatible!(rc, Rc, *mut i32); +test_abi_compatible!(arc, Arc, *mut i32); // `repr(transparent)` compatibility. #[repr(transparent)] @@ -160,7 +323,7 @@ mod unsized_ { use super::*; test_transparent_unsized!(str_, str); test_transparent_unsized!(slice, [u8]); - test_transparent_unsized!(dyn_trait, dyn std::any::Any); + test_transparent_unsized!(dyn_trait, dyn Any); } // RFC 3391 . @@ -185,7 +348,7 @@ test_nonnull!(ref_unsized, &[i32]); test_nonnull!(mut_unsized, &mut [i32]); test_nonnull!(fn_, fn()); test_nonnull!(nonnull, NonNull); -test_nonnull!(nonnull_unsized, NonNull); +test_nonnull!(nonnull_unsized, NonNull); test_nonnull!(non_zero, NonZeroI32); fn main() {} diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs index 0cfc44cd09d80..cca2e8db74d75 100644 --- a/tests/ui/abi/relocation_model_pic.rs +++ b/tests/ui/abi/relocation_model_pic.rs @@ -1,7 +1,6 @@ // run-pass // compile-flags: -C relocation-model=pic -// ignore-emscripten no pic -// ignore-wasm +// needs-relocation-model-pic #![feature(cfg_relocation_model)] diff --git a/tests/ui/async-await/feature-self-return-type.rs b/tests/ui/async-await/feature-self-return-type.rs index 41f887430c1cb..ae6f766d247e6 100644 --- a/tests/ui/async-await/feature-self-return-type.rs +++ b/tests/ui/async-await/feature-self-return-type.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(impl_trait_projections)] // This test checks that we emit the correct borrowck error when `Self` is used as a return type. // See #61949 for context. diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr index 747c54b669440..dc160bfbf6179 100644 --- a/tests/ui/async-await/feature-self-return-type.stderr +++ b/tests/ui/async-await/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:22:18 + --> $DIR/feature-self-return-type.rs:21:18 | LL | let x = { | - borrow later stored here diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs index 974f5aaff83c3..3e2739a164f17 100644 --- a/tests/ui/async-await/in-trait/async-associated-types.rs +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -2,7 +2,6 @@ // edition: 2021 #![feature(async_fn_in_trait)] -#![feature(impl_trait_projections)] #![allow(incomplete_features)] use std::fmt::Debug; diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr index e0c1acfedfc36..41e84466a144e 100644 --- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr @@ -2,7 +2,7 @@ error[E0391]: cycle detected when computing layout of `{async fn body@$DIR/indir | = note: ...which requires computing layout of `<::Second as Second>::{opaque#0}`... = note: ...which again requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:35:27: 37:6}`, completing the cycle - = note: cycle used when computing layout of `::second::{opaque#0}` + = note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:8:13: 10:6}` = 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: aborting due to previous error diff --git a/tests/ui/async-await/issue-61949-self-return-type.rs b/tests/ui/async-await/issue-61949-self-return-type.rs deleted file mode 100644 index d73dbc6e828f3..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// edition:2018 -// gate-test-impl_trait_projections - -// This test checks that `Self` is prohibited as a return type. See #61949 for context. - -pub struct Foo<'a> { - pub bar: &'a i32, -} - -impl<'a> Foo<'a> { - pub async fn new(_bar: &'a i32) -> Self { - //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - Foo { - bar: &22 - } - } -} - -async fn foo() { - let x = { - let bar = 22; - Foo::new(&bar).await - //~^ ERROR `bar` does not live long enough - }; - drop(x); -} - -fn main() { } diff --git a/tests/ui/async-await/issue-61949-self-return-type.stderr b/tests/ui/async-await/issue-61949-self-return-type.stderr deleted file mode 100644 index ac85ed2887abc..0000000000000 --- a/tests/ui/async-await/issue-61949-self-return-type.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-61949-self-return-type.rs:11:40 - | -LL | pub async fn new(_bar: &'a i32) -> Self { - | ^^^^ help: consider spelling out the type instead: `Foo<'a>` - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - -error[E0597]: `bar` does not live long enough - --> $DIR/issue-61949-self-return-type.rs:22:18 - | -LL | let x = { - | - borrow later stored here -LL | let bar = 22; - | --- binding `bar` declared here -LL | Foo::new(&bar).await - | ^^^^ borrowed value does not live long enough -LL | -LL | }; - | - `bar` dropped here while still borrowed - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0597, E0658. -For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/issues/issue-78600.rs b/tests/ui/async-await/issues/issue-78600.rs index 8aaeaecf3e1da..4303fc7952f2b 100644 --- a/tests/ui/async-await/issues/issue-78600.rs +++ b/tests/ui/async-await/issues/issue-78600.rs @@ -1,10 +1,10 @@ +// check-pass // edition:2018 struct S<'a>(&'a i32); impl<'a> S<'a> { async fn new(i: &'a i32) -> Result { - //~^ ERROR: `async fn` Ok(S(&22)) } } diff --git a/tests/ui/async-await/issues/issue-78600.stderr b/tests/ui/async-await/issues/issue-78600.stderr deleted file mode 100644 index 37eafa996c535..0000000000000 --- a/tests/ui/async-await/issues/issue-78600.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/issue-78600.rs:6:33 - | -LL | async fn new(i: &'a i32) -> Result { - | ^^^^^^^----^^^^^ - | | - | help: consider spelling out the type instead: `S<'a>` - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs new file mode 100644 index 0000000000000..a83830178d40e --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.rs @@ -0,0 +1,44 @@ +// Test that when adt_const_params is not enabled, we suggest adding the feature only when +// it would be possible for the type to be used as a const generic or when it's likely +// possible for the user to fix their type to be used. + +// Can never be used as const generics. +fn uwu_0() {} +//~^ ERROR: forbidden as the type of a const generic + +// Needs the feature but can be used, so suggest adding the feature. +fn owo_0() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// Can only be used in const generics with changes. +struct Meow { + meow: u8, +} + +fn meow_0() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_1() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_2() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` +fn meow_3() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// This is suboptimal that it thinks it can be used +// but better to suggest the feature to the user. +fn meow_4() {} +//~^ ERROR: forbidden as the type of a const generic +//~^^ HELP: add `#![feature(adt_const_params)]` + +// Non-local ADT that does not impl `ConstParamTy` +fn nya_0() {} +//~^ ERROR: forbidden as the type of a const generic +fn nya_1>() {} +//~^ ERROR: forbidden as the type of a const generic + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr new file mode 100644 index 0000000000000..04527e3158ed1 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr @@ -0,0 +1,80 @@ +error: `&'static mut ()` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:6:19 + | +LL | fn uwu_0() {} + | ^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: `&'static u32` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:10:19 + | +LL | fn owo_0() {} + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `Meow` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:19:20 + | +LL | fn meow_0() {} + | ^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `&'static Meow` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:22:20 + | +LL | fn meow_1() {} + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `[Meow; 100]` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:25:20 + | +LL | fn meow_2() {} + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `(Meow, u8)` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:28:20 + | +LL | fn meow_3() {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `(Meow, String)` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:34:20 + | +LL | fn meow_4() {} + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + +error: `String` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:39:19 + | +LL | fn nya_0() {} + | ^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: `Vec` is forbidden as the type of a const generic parameter + --> $DIR/suggest_feature_only_when_possible.rs:41:19 + | +LL | fn nya_1>() {} + | ^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr index 656bc29466f23..ffe4528598850 100644 --- a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -35,7 +35,7 @@ LL | struct A; | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:14:15 @@ -44,7 +44,7 @@ LL | impl A { | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:22:15 @@ -53,7 +53,7 @@ LL | impl B for A {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:26:17 @@ -62,7 +62,7 @@ LL | fn bar() {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&u8` is forbidden as the type of a const generic parameter --> $DIR/const-param-elided-lifetime.rs:17:21 @@ -71,7 +71,7 @@ LL | fn foo(&self) {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 10 previous errors diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr index f829526ca1dc8..daeeadeed7cfd 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -21,7 +21,7 @@ LL | pub struct Dependent([(); N]); | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `[u8; N]` is forbidden as the type of a const generic parameter --> $DIR/const-param-type-depends-on-const-param.rs:15:35 @@ -30,7 +30,7 @@ LL | pub struct SelfDependent; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr index 89ca36b0f6314..aeb19dc75322d 100644 --- a/tests/ui/const-generics/float-generic.simple.stderr +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -5,7 +5,6 @@ LL | fn foo() {} | ^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: aborting due to previous error diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr index d984449e6ca6e..2d316fba1e90a 100644 --- a/tests/ui/const-generics/fn-const-param-call.min.stderr +++ b/tests/ui/const-generics/fn-const-param-call.min.stderr @@ -3,12 +3,16 @@ error: using function pointers as const generic parameters is forbidden | LL | struct Wrapper u32>; | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/fn-const-param-call.rs:13:15 | LL | impl u32> Wrapper { | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr index f0767a10994a5..a7afa48427594 100644 --- a/tests/ui/const-generics/fn-const-param-infer.min.stderr +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr index 956e9c9c988a4..64d1e0bcff4e0 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -23,7 +23,7 @@ LL | struct B { | ^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index b8a1027c9ebdb..4c45339b93b37 100644 --- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -14,7 +14,7 @@ LL | trait Trait {} | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr index 71a7051f25bfa..fc10aba0fecd0 100644 --- a/tests/ui/const-generics/issues/issue-56445-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr @@ -13,7 +13,7 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index 9c0e5179cc4c2..eb8b9732f58c8 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -13,7 +13,7 @@ LL | fn foo() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index 9f6c7ccf3fe74..9d80f1cd01bc6 100644 --- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -5,7 +5,7 @@ LL | fn test() { | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr index df04c4896b45a..c8b9f17196aca 100644 --- a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -5,7 +5,7 @@ LL | struct Const {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr index 1b4517087e223..fc6cef9d44e55 100644 --- a/tests/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-71169.min.stderr b/tests/ui/const-generics/issues/issue-71169.min.stderr index ebfb24bec28df..bba92f32a7842 100644 --- a/tests/ui/const-generics/issues/issue-71169.min.stderr +++ b/tests/ui/const-generics/issues/issue-71169.min.stderr @@ -13,7 +13,7 @@ LL | fn foo() {} | ^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index e1e140071fc13..e16d3b7a8a469 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -19,12 +19,16 @@ error: using function pointers as const generic parameters is forbidden | LL | pub fn call_me(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/issue-71381.rs:23:19 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr index 715037bd5f1e8..217166d847937 100644 --- a/tests/ui/const-generics/issues/issue-71382.min.stderr +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn test(&self) { | ^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr index b33d7cf9850fa..b01936f4d2513 100644 --- a/tests/ui/const-generics/issues/issue-71611.min.stderr +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -11,6 +11,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn func(outer: A) { | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr index eedd73c4dcc0a..b010996b89692 100644 --- a/tests/ui/const-generics/issues/issue-72352.min.stderr +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { | ^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr index f03354fc472c0..fdf057bdbe47d 100644 --- a/tests/ui/const-generics/issues/issue-73491.min.stderr +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -5,7 +5,7 @@ LL | fn hoge() {} | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr index 0a7db62472a9f..bed0a02a72673 100644 --- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -5,7 +5,7 @@ LL | fn a() {} | ^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-74101.min.stderr b/tests/ui/const-generics/issues/issue-74101.min.stderr index 134c248347d3c..7852ce5bcfcea 100644 --- a/tests/ui/const-generics/issues/issue-74101.min.stderr +++ b/tests/ui/const-generics/issues/issue-74101.min.stderr @@ -5,7 +5,7 @@ LL | fn test() {} | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter --> $DIR/issue-74101.rs:9:21 @@ -14,7 +14,7 @@ LL | struct Foo; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr index bbcf8682b7119..affeca167e970 100644 --- a/tests/ui/const-generics/issues/issue-74255.min.stderr +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -5,7 +5,7 @@ LL | fn ice_struct_fn() {} | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr index c37ee93d420fd..a5dbe10b78a32 100644 --- a/tests/ui/const-generics/issues/issue-74950.min.stderr +++ b/tests/ui/const-generics/issues/issue-74950.min.stderr @@ -5,7 +5,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -14,7 +14,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -23,7 +23,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -32,7 +32,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `Inner` is forbidden as the type of a const generic parameter --> $DIR/issue-74950.rs:20:23 @@ -41,7 +41,7 @@ LL | struct Outer; | ^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 5 previous errors diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr index 46af19ef39540..e316b4624a007 100644 --- a/tests/ui/const-generics/issues/issue-75047.min.stderr +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -5,7 +5,7 @@ LL | struct Foo::value()]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/lifetime-in-const-param.stderr b/tests/ui/const-generics/lifetime-in-const-param.stderr index 8fd9068e8efd2..c2fcdcf1a7128 100644 --- a/tests/ui/const-generics/lifetime-in-const-param.stderr +++ b/tests/ui/const-generics/lifetime-in-const-param.stderr @@ -11,7 +11,7 @@ LL | struct S<'a, const N: S2>(&'a ()); | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr index 4ddbadb54661b..8cc75dbaff9c3 100644 --- a/tests/ui/const-generics/min_const_generics/complex-types.stderr +++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:6:21 @@ -14,7 +14,7 @@ LL | struct Bar; | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `No` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:11:21 @@ -23,7 +23,7 @@ LL | struct Fez; | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static u8` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:14:21 @@ -32,7 +32,7 @@ LL | struct Faz; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `!` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:17:21 @@ -41,7 +41,6 @@ LL | struct Fiz; | ^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:20:19 @@ -50,7 +49,7 @@ LL | enum Goo { A, B } | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:23:20 @@ -59,7 +58,7 @@ LL | union Boo { a: () } | ^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 7 previous errors diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr index 257a9e31e14b2..ca5af5f969f58 100644 --- a/tests/ui/const-generics/nested-type.min.stderr +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -30,7 +30,7 @@ LL | | }]>; | |__^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr index 803ed9c959752..9f727231edfbe 100644 --- a/tests/ui/const-generics/projection-as-arg-const.stderr +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -5,7 +5,6 @@ LL | pub fn foo::Identity>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` error: aborting due to previous error diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr index 04bc46cb4ab12..1eb238255abc2 100644 --- a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -3,12 +3,16 @@ error: using raw pointers as const generic parameters is forbidden | LL | struct Const; | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: using raw pointers as const generic parameters is forbidden --> $DIR/raw-ptr-const-param-deref.rs:11:15 | LL | impl Const

{ | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr index 310422aafcd35..13fbc34e51a0d 100644 --- a/tests/ui/const-generics/raw-ptr-const-param.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -3,6 +3,8 @@ error: using raw pointers as const generic parameters is forbidden | LL | struct Const; | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr index fed802f6adc6b..3c086f59b2788 100644 --- a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr +++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -5,7 +5,7 @@ LL | struct ConstString; | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static [u8]` is forbidden as the type of a const generic parameter --> $DIR/slice-const-param-mismatch.rs:9:28 @@ -14,7 +14,7 @@ LL | struct ConstBytes; | ^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr index 53fca6e884a9a..d45f749246c8e 100644 --- a/tests/ui/const-generics/std/const-generics-range.min.stderr +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -5,7 +5,7 @@ LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeFrom` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:13:28 @@ -14,7 +14,7 @@ LL | struct _RangeFrom>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeFull` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:18:28 @@ -23,7 +23,7 @@ LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:24:33 @@ -32,7 +32,7 @@ LL | struct _RangeInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeTo` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:29:26 @@ -41,7 +41,7 @@ LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `RangeToInclusive` is forbidden as the type of a const generic parameter --> $DIR/const-generics-range.rs:34:35 @@ -50,7 +50,7 @@ LL | struct _RangeToInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr index 039c4276c8b77..f18e149464d3d 100644 --- a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -5,7 +5,7 @@ LL | struct Const; | ^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index b8fbb3979799d..6490592c1e1e6 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> { | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:18:25 @@ -14,7 +14,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr index ad522aead9050..3f42feea562ab 100644 --- a/tests/ui/const-generics/type-dependent/issue-71382.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden | LL | fn test u8>(&self) -> u8 { | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` error: aborting due to previous error diff --git a/tests/ui/did_you_mean/bad-assoc-expr.stderr b/tests/ui/did_you_mean/bad-assoc-expr.stderr index c295cac9aa4b2..b83078e21b6a1 100644 --- a/tests/ui/did_you_mean/bad-assoc-expr.stderr +++ b/tests/ui/did_you_mean/bad-assoc-expr.stderr @@ -2,60 +2,104 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:3:5 | LL | [i32; 4]::clone(&a); - | ^^^^^^^^^^^^^^^ help: try: `<[i32; 4]>::clone` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[i32; 4]>::clone(&a); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:6:5 | LL | [i32]::as_ref(&a); - | ^^^^^^^^^^^^^ help: try: `<[i32]>::as_ref` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[i32]>::as_ref(&a); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:9:5 | LL | (u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:12:5 | LL | (u8, u8)::clone(&(0, 0)); - | ^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::clone` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8, u8)>::clone(&(0, 0)); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:15:6 | LL | &(u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | &<(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:18:10 | LL | 10 + (u8)::clone(&0); - | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | 10 + <(u8)>::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:32:13 | LL | let _ = ty!()::clone(&0); - | ^^^^^^^^^^^^ help: try: `::clone` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | let _ = ::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:34:5 | LL | ty!()::clone(&0); - | ^^^^^^^^^^^^ help: try: `::clone` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ::clone(&0); + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:23:19 | LL | ($ty: ty) => ($ty::clone(&0)) - | ^^^^^^^^^^ help: try: `<$ty>::clone` + | ^^^ ... LL | expr!(u8); | --------- in this macro invocation | = note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::clone(&0)) + | + + error: aborting due to 9 previous errors diff --git a/tests/ui/did_you_mean/bad-assoc-pat.stderr b/tests/ui/did_you_mean/bad-assoc-pat.stderr index 19d173f1b423c..8bdeb8ffdd0a8 100644 --- a/tests/ui/did_you_mean/bad-assoc-pat.stderr +++ b/tests/ui/did_you_mean/bad-assoc-pat.stderr @@ -2,42 +2,71 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:3:9 | LL | [u8]::AssocItem => {} - | ^^^^^^^^^^^^^^^ help: try: `<[u8]>::AssocItem` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <[u8]>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:6:9 | LL | (u8, u8)::AssocItem => {} - | ^^^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocItem` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <(u8, u8)>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:9:9 | LL | _::AssocItem => {} - | ^^^^^^^^^^^^ help: try: `<_>::AssocItem` + | ^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | <_>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:14:10 | LL | &(u8,)::AssocItem => {} - | ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | &<(u8,)>::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:32:9 | LL | ty!()::AssocItem => {} - | ^^^^^^^^^^^^^^^^ help: try: `::AssocItem` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ::AssocItem => {} + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:21:19 | LL | ($ty: ty) => ($ty::AssocItem) - | ^^^^^^^^^^^^^^ help: try: `<$ty>::AssocItem` + | ^^^ ... LL | pat!(u8) => {} | -------- in this macro invocation | = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::AssocItem) + | + + error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope --> $DIR/bad-assoc-pat.rs:3:15 diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 55096e95df7e0..efa6bb6682407 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -2,60 +2,104 @@ error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:1:10 | LL | type A = [u8; 4]::AssocTy; - | ^^^^^^^^^^^^^^^^ help: try: `<[u8; 4]>::AssocTy` + | ^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type A = <[u8; 4]>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:5:10 | LL | type B = [u8]::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<[u8]>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type B = <[u8]>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:9:10 | LL | type C = (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type C = <(u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:13:10 | LL | type D = (u8, u8)::AssocTy; - | ^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocTy` + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type D = <(u8, u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:17:10 | LL | type E = _::AssocTy; - | ^^^^^^^^^^ help: try: `<_>::AssocTy` + | ^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type E = <_>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type F = &'static <(u8)>::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type G = ::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:46:10 | LL | type I = ty!()::AssocTy; - | ^^^^^^^^^^^^^^ help: try: `::AssocTy` + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type I = ::AssocTy; + | + + error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:39:19 | LL | ($ty: ty) => ($ty::AssocTy); - | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` + | ^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::AssocTy); + | + + error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 68e15e6f8fe81..a77920430672e 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -1,8 +1,10 @@ -error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found +error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0374.rs:8:1 | LL | impl CoerceUnsized> for Foo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected a single field to be coerced, none found error: aborting due to previous error diff --git a/tests/ui/error-codes/E0377.stderr b/tests/ui/error-codes/E0377.stderr index bf7d8c8d39d2a..664e499ec23a0 100644 --- a/tests/ui/error-codes/E0377.stderr +++ b/tests/ui/error-codes/E0377.stderr @@ -1,8 +1,10 @@ -error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with the same definition; expected `Foo`, found `Bar` +error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures --> $DIR/E0377.rs:12:1 | LL | impl CoerceUnsized> for Foo where T: CoerceUnsized {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected coercion between the same definition; expected `Foo`, found `Bar` error: aborting due to previous error diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr index d8f089a28b7e1..13b9b84f0be4e 100644 --- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr @@ -5,7 +5,7 @@ LL | struct Foo; | ^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to previous error diff --git a/tests/ui/foreign/foreign-fn-linkname.rs b/tests/ui/foreign/foreign-fn-linkname.rs index f6d820594f966..d1d6e703e3dd4 100644 --- a/tests/ui/foreign/foreign-fn-linkname.rs +++ b/tests/ui/foreign/foreign-fn-linkname.rs @@ -2,6 +2,9 @@ // ignore-wasm32-bare no libc to test ffi with // ignore-sgx no libc +// Ensure no false positive on "unused extern crate" lint +#![deny(unused_extern_crates)] + #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/generic-const-items/elided-lifetimes.stderr b/tests/ui/generic-const-items/elided-lifetimes.stderr index 8cd3f9ee7a918..e7df8ca5cfd99 100644 --- a/tests/ui/generic-const-items/elided-lifetimes.stderr +++ b/tests/ui/generic-const-items/elided-lifetimes.stderr @@ -28,7 +28,7 @@ LL | const I: &str = ""; | ^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/bound-normalization-fail.rs b/tests/ui/impl-trait/bound-normalization-fail.rs index 3329592478d6f..566a4a7adccb9 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.rs +++ b/tests/ui/impl-trait/bound-normalization-fail.rs @@ -39,8 +39,7 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - //~| ERROR: type mismatch + //~^ ERROR: type mismatch Foo(()) } } diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr index f04a753a0e8bd..fcac9ac34dbc3 100644 --- a/tests/ui/impl-trait/bound-normalization-fail.stderr +++ b/tests/ui/impl-trait/bound-normalization-fail.stderr @@ -19,21 +19,12 @@ help: consider constraining the associated type `::Assoc LL | fn foo_fail>() -> impl FooLike { | ++++++++++++ -error[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:41:41 - | -LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #103532 for more information - = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable - error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` --> $DIR/bound-normalization-fail.rs:41:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` -... +LL | LL | Foo(()) | ------- return type was inferred to be `Foo<()>` here | @@ -49,7 +40,6 @@ help: consider constraining the associated type `>::As LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { | ++++++++++++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0658. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs new file mode 100644 index 0000000000000..9c067cb693444 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.rs @@ -0,0 +1,21 @@ +#![feature(rustc_attrs)] +#![rustc_variance_of_opaques] + +trait Bar<'a> { + type Assoc: From<()>; +} + +fn foo<'a, T: Bar<'a>>() -> impl Into { + //~^ ERROR [o, o] + // captures both T and 'a invariantly + () +} + +fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + //~^ ERROR [o, o, o] + // captures both T and 'a invariantly, and also duplicates `'a` + // i.e. the opaque looks like `impl Into<>::Assoc> + 'a_duplicated` + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr new file mode 100644 index 0000000000000..9d52001b02460 --- /dev/null +++ b/tests/ui/impl-trait/capture-lifetime-not-in-hir.stderr @@ -0,0 +1,14 @@ +error: [o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:8:29 + | +LL | fn foo<'a, T: Bar<'a>>() -> impl Into { + | ^^^^^^^^^^^^^^^^^^^ + +error: [o, o, o] + --> $DIR/capture-lifetime-not-in-hir.rs:14:30 + | +LL | fn foo2<'a, T: Bar<'a>>() -> impl Into + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/feature-self-return-type.rs b/tests/ui/impl-trait/feature-self-return-type.rs index 51877e9cc3c43..7555df1b2c709 100644 --- a/tests/ui/impl-trait/feature-self-return-type.rs +++ b/tests/ui/impl-trait/feature-self-return-type.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(impl_trait_projections)] // This test checks that we emit the correct borrowck error when `Self` or a projection is used as // a return type. See #61949 for context. diff --git a/tests/ui/impl-trait/feature-self-return-type.stderr b/tests/ui/impl-trait/feature-self-return-type.stderr index b9b8d00ce308b..e7113a9dfb1b9 100644 --- a/tests/ui/impl-trait/feature-self-return-type.stderr +++ b/tests/ui/impl-trait/feature-self-return-type.stderr @@ -1,5 +1,5 @@ error[E0597]: `bar` does not live long enough - --> $DIR/feature-self-return-type.rs:23:22 + --> $DIR/feature-self-return-type.rs:22:22 | LL | let x = { | - borrow later stored here @@ -12,7 +12,7 @@ LL | }; | - `bar` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:63:17 + --> $DIR/feature-self-return-type.rs:62:17 | LL | let x = { | - borrow later stored here @@ -25,7 +25,7 @@ LL | }; | - `y` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/feature-self-return-type.rs:95:17 + --> $DIR/feature-self-return-type.rs:94:17 | LL | let x = { | - borrow later stored here diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.stderr b/tests/ui/invalid_dispatch_from_dyn_impls.stderr index b5b32d2f0bd36..172ee7ade4903 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/tests/ui/invalid_dispatch_from_dyn_impls.stderr @@ -15,11 +15,13 @@ LL | impl DispatchFromDyn> for Multipl = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`) -error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1 | LL | impl DispatchFromDyn> for NothingToCoerce {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected a single field to be coerced, none found error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` --> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1 diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 01ec69a6110fa..92a2ef2f432f1 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -56,7 +56,7 @@ LL | fn d() {} | ^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter --> $DIR/unusual-rib-combinations.rs:29:21 @@ -65,7 +65,7 @@ LL | struct Bar Foo<'a>)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` - = help: more complex types are supported with `#![feature(adt_const_params)]` + = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types error: aborting due to 9 previous errors diff --git a/tests/ui/lint/noop-method-call.fixed b/tests/ui/lint/noop-method-call.fixed index eeb80279fd816..4d9834f7df625 100644 --- a/tests/ui/lint/noop-method-call.fixed +++ b/tests/ui/lint/noop-method-call.fixed @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![feature(rustc_attrs)] #![allow(unused)] use std::borrow::Borrow; @@ -49,3 +50,15 @@ fn non_generic(non_clone_type: &PlainType) { non_clone_type; //~^ WARN call to `.clone()` on a reference in this situation does nothing } + +struct DiagnosticClone; +impl Clone for DiagnosticClone { + #[rustc_diagnostic_item = "other_clone"] + fn clone(&self) -> Self { + DiagnosticClone + } +} + +fn with_other_diagnostic_item(x: DiagnosticClone) { + x.clone(); +} diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index 9569a0dfc617e..6242a00e03348 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![feature(rustc_attrs)] #![allow(unused)] use std::borrow::Borrow; @@ -49,3 +50,15 @@ fn non_generic(non_clone_type: &PlainType) { non_clone_type.clone(); //~^ WARN call to `.clone()` on a reference in this situation does nothing } + +struct DiagnosticClone; +impl Clone for DiagnosticClone { + #[rustc_diagnostic_item = "other_clone"] + fn clone(&self) -> Self { + DiagnosticClone + } +} + +fn with_other_diagnostic_item(x: DiagnosticClone) { + x.clone(); +} diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index aefc2706fd529..d04f44022eefd 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -1,5 +1,5 @@ warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:15:25 + --> $DIR/noop-method-call.rs:16:25 | LL | let _ = &mut encoded.clone(); | ^^^^^^^^ help: remove this redundant call @@ -8,7 +8,7 @@ LL | let _ = &mut encoded.clone(); = note: `#[warn(noop_method_call)]` on by default warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:17:21 + --> $DIR/noop-method-call.rs:18:21 | LL | let _ = &encoded.clone(); | ^^^^^^^^ help: remove this redundant call @@ -16,7 +16,7 @@ LL | let _ = &encoded.clone(); = note: the type `[u8]` does not implement `Clone`, so calling `clone` on `&[u8]` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:23:71 + --> $DIR/noop-method-call.rs:24:71 | LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); | ^^^^^^^^ help: remove this redundant call @@ -24,7 +24,7 @@ LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clon = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:31:63 + --> $DIR/noop-method-call.rs:32:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ help: remove this redundant call @@ -32,7 +32,7 @@ LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); = note: the type `PlainType` does not implement `Deref`, so calling `deref` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.borrow()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:35:66 + --> $DIR/noop-method-call.rs:36:66 | LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); | ^^^^^^^^^ help: remove this redundant call @@ -40,7 +40,7 @@ LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); = note: the type `PlainType` does not implement `Borrow`, so calling `borrow` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:44:19 + --> $DIR/noop-method-call.rs:45:19 | LL | non_clone_type.clone(); | ^^^^^^^^ help: remove this redundant call @@ -48,7 +48,7 @@ LL | non_clone_type.clone(); = note: the type `PlainType` does not implement `Clone`, so calling `clone` on `&PlainType` copies the reference, which does not do anything and can be removed warning: call to `.clone()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:49:19 + --> $DIR/noop-method-call.rs:50:19 | LL | non_clone_type.clone(); | ^^^^^^^^ help: remove this redundant call diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 7745d4ef4c3a2..fba8789e999ed 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -36,6 +36,8 @@ unsafe fn ref_to_mut() { //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::mem::transmute::<_, *mut i32>(num); //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::cell::UnsafeCell::raw_get( //~^ ERROR casting `&T` to `&mut T` is undefined behavior num as *const i32 as *const std::cell::UnsafeCell @@ -47,8 +49,20 @@ unsafe fn ref_to_mut() { let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; let _num = &mut *deferred; //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let deferred_rebind = deferred; + let _num = &mut *deferred_rebind; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const _ as usize as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior + let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32); + //~^ ERROR casting `&T` to `&mut T` is undefined behavior + + static NUM: &'static i32 = &2; + let num = NUM as *const i32 as *mut i32; + let num = num; + let num = num; + let _num = &mut *num; + //~^ ERROR casting `&T` to `&mut T` is undefined behavior unsafe fn generic_ref_cast_mut(this: &T) -> &mut T { &mut *((this as *const _) as *mut _) @@ -85,6 +99,8 @@ unsafe fn assign_to_ref() { //~^ ERROR assigning to `&T` is undefined behavior *std::mem::transmute::<_, *mut i32>(num) += 1; //~^ ERROR assigning to `&T` is undefined behavior + *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1; + //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write( //~^ ERROR assigning to `&T` is undefined behavior std::mem::transmute::<*const i32, *mut i32>(num), @@ -94,6 +110,9 @@ unsafe fn assign_to_ref() { let value = num as *const i32 as *mut i32; *value = 1; //~^ ERROR assigning to `&T` is undefined behavior + let value_rebind = value; + *value_rebind = 1; + //~^ ERROR assigning to `&T` is undefined behavior *(num as *const i32).cast::().cast_mut() = 2; //~^ ERROR assigning to `&T` is undefined behavior *(num as *const _ as usize as *mut i32) = 2; @@ -111,6 +130,7 @@ unsafe fn assign_to_ref() { } } +const RAW_PTR: *mut u8 = 1 as *mut u8; unsafe fn no_warn() { let num = &3i32; let mut_num = &mut 3i32; @@ -125,6 +145,9 @@ unsafe fn no_warn() { let mut value = 3; let value: *const i32 = &mut value; *(value as *const i16 as *mut i16) = 42; + *RAW_PTR = 42; // RAW_PTR is defined outside the function body, + // make sure we don't ICE on it when trying to + // determine if we should lint on it or not. fn safe_as_mut(x: &std::cell::UnsafeCell) -> &mut T { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 1189942c809dd..8f89cf9805b04 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -82,6 +82,14 @@ LL | let _num = &mut *std::mem::transmute::<_, *mut i32>(num); error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` --> $DIR/reference_casting.rs:39:16 | +LL | let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:41:16 + | LL | let _num = &mut *std::cell::UnsafeCell::raw_get( | ________________^ LL | | @@ -92,7 +100,7 @@ LL | | ); = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:45:16 + --> $DIR/reference_casting.rs:47:16 | LL | let deferred = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -102,7 +110,7 @@ LL | let _num = &mut *deferred; = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:48:16 + --> $DIR/reference_casting.rs:50:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; | ---------------------------------------------------------------------------- casting happend here @@ -112,7 +120,18 @@ LL | let _num = &mut *deferred; = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:50:16 + --> $DIR/reference_casting.rs:53:16 + | +LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; + | ---------------------------------------------------------------------------- casting happend here +... +LL | let _num = &mut *deferred_rebind; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:55:16 | LL | let _num = &mut *(num as *const _ as usize as *mut i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,7 +139,26 @@ LL | let _num = &mut *(num as *const _ as usize as *mut i32); = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:54:9 + --> $DIR/reference_casting.rs:57:16 + | +LL | let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:64:16 + | +LL | let num = NUM as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | let _num = &mut *num; + | ^^^^^^^^^ + | + = note: for more information, visit + +error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + --> $DIR/reference_casting.rs:68:9 | LL | &mut *((this as *const _) as *mut _) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,7 +166,7 @@ LL | &mut *((this as *const _) as *mut _) = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:59:18 + --> $DIR/reference_casting.rs:73:18 | LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +174,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con = note: for more information, visit error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - --> $DIR/reference_casting.rs:64:18 + --> $DIR/reference_casting.rs:78:18 | LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +182,7 @@ LL | unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *con = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:74:5 + --> $DIR/reference_casting.rs:88:5 | LL | *(a as *const _ as *mut _) = String::from("Replaced"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -152,7 +190,7 @@ LL | *(a as *const _ as *mut _) = String::from("Replaced"); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:76:5 + --> $DIR/reference_casting.rs:90:5 | LL | *(a as *const _ as *mut String) += " world"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +198,7 @@ LL | *(a as *const _ as *mut String) += " world"; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:78:5 + --> $DIR/reference_casting.rs:92:5 | LL | *std::ptr::from_ref(num).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -168,7 +206,7 @@ LL | *std::ptr::from_ref(num).cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:80:5 + --> $DIR/reference_casting.rs:94:5 | LL | *std::ptr::from_ref({ num }).cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +214,7 @@ LL | *std::ptr::from_ref({ num }).cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:82:5 + --> $DIR/reference_casting.rs:96:5 | LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +222,7 @@ LL | *{ std::ptr::from_ref(num) }.cast_mut() += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:84:5 + --> $DIR/reference_casting.rs:98:5 | LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,7 +230,7 @@ LL | *(std::ptr::from_ref({ num }) as *mut i32) += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:86:5 + --> $DIR/reference_casting.rs:100:5 | LL | *std::mem::transmute::<_, *mut i32>(num) += 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +238,15 @@ LL | *std::mem::transmute::<_, *mut i32>(num) += 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:88:5 + --> $DIR/reference_casting.rs:102:5 + | +LL | *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:104:5 | LL | / std::ptr::write( LL | | @@ -212,7 +258,7 @@ LL | | ); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:95:5 + --> $DIR/reference_casting.rs:111:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -222,7 +268,18 @@ LL | *value = 1; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:97:5 + --> $DIR/reference_casting.rs:114:5 + | +LL | let value = num as *const i32 as *mut i32; + | ----------------------------- casting happend here +... +LL | *value_rebind = 1; + | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit + +error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + --> $DIR/reference_casting.rs:116:5 | LL | *(num as *const i32).cast::().cast_mut() = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,7 +287,7 @@ LL | *(num as *const i32).cast::().cast_mut() = 2; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:99:5 + --> $DIR/reference_casting.rs:118:5 | LL | *(num as *const _ as usize as *mut i32) = 2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +295,7 @@ LL | *(num as *const _ as usize as *mut i32) = 2; = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:101:5 + --> $DIR/reference_casting.rs:120:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -249,7 +306,7 @@ LL | std::ptr::write(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:103:5 + --> $DIR/reference_casting.rs:122:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -260,7 +317,7 @@ LL | std::ptr::write_unaligned(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:105:5 + --> $DIR/reference_casting.rs:124:5 | LL | let value = num as *const i32 as *mut i32; | ----------------------------- casting happend here @@ -271,12 +328,12 @@ LL | std::ptr::write_volatile(value, 2); = note: for more information, visit error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - --> $DIR/reference_casting.rs:109:9 + --> $DIR/reference_casting.rs:128:9 | LL | *(this as *const _ as *mut _) = a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, visit -error: aborting due to 32 previous errors +error: aborting due to 38 previous errors diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs deleted file mode 100644 index 0ccd441cc6489..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs +++ /dev/null @@ -1,11 +0,0 @@ -// gate-test-packed_bundled_libs - -// ignore-wasm32-bare -// compile-flags: --crate-type rlib -// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -// build-fail - -#[link(name = "rust_test_helpers", kind = "static", modifiers = "+bundle,+whole-archive")] -extern "C" {} - -fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr deleted file mode 100644 index 8a9fed740b04e..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - -error: aborting due to previous error - diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs deleted file mode 100644 index 18d4b52a34c3d..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs +++ /dev/null @@ -1,8 +0,0 @@ -// gate-test-packed_bundled_libs - -// ignore-wasm32-bare -// compile-flags: -l static:+bundle,+whole-archive=rust_test_helpers --crate-type rlib -// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs -// build-fail - -fn main() {} diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr deleted file mode 100644 index 8a9fed740b04e..0000000000000 --- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs - -error: aborting due to previous error - diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs index 38a80f8b6703a..751959f55bb6e 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs @@ -2,6 +2,7 @@ // run-fail // check-run-results // exec-env:RUST_BACKTRACE=1 +// needs-unwind // ignore-android FIXME #17520 // ignore-wasm no panic support // ignore-openbsd no support for libbacktrace without filename diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr index 2b648a0cad2ea..664ebaa4c51a6 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:57:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs index c872084f0333e..134e13233da51 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames.rs @@ -2,6 +2,7 @@ // run-fail // check-run-results // exec-env:RUST_BACKTRACE=1 +// needs-unwind // ignore-android FIXME #17520 // ignore-wasm no panic support // ignore-openbsd no support for libbacktrace without filename diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr index 5b37268409679..bc252fde1f6ab 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:53:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/parser/issues/issue-89388.stderr b/tests/ui/parser/issues/issue-89388.stderr index cf28bef0f4ab0..366d05c2d9480 100644 --- a/tests/ui/parser/issues/issue-89388.stderr +++ b/tests/ui/parser/issues/issue-89388.stderr @@ -2,7 +2,12 @@ error: missing angle brackets in associated item path --> $DIR/issue-89388.rs:5:24 | LL | let _ = option.map([_]::to_vec); - | ^^^^^^^^^^^ help: try: `<[_]>::to_vec` + | ^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | let _ = option.map(<[_]>::to_vec); + | + + error: aborting due to previous error diff --git a/tests/ui/resolve/associated-fn-called-as-fn.stderr b/tests/ui/resolve/associated-fn-called-as-fn.stderr index fbdea30d551fd..7d28b959a1a48 100644 --- a/tests/ui/resolve/associated-fn-called-as-fn.stderr +++ b/tests/ui/resolve/associated-fn-called-as-fn.stderr @@ -2,13 +2,23 @@ error[E0425]: cannot find function `collect_primary` in this scope --> $DIR/associated-fn-called-as-fn.rs:6:30 | LL | '0'..='9' => collect_primary(&c), - | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + | ^^^^^^^^^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | '0'..='9' => Self::collect_primary(&c), + | ++++++ error[E0425]: cannot find function `collect_primary` in this scope --> $DIR/associated-fn-called-as-fn.rs:23:30 | LL | '0'..='9' => collect_primary(&c), - | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + | ^^^^^^^^^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | '0'..='9' => Self::collect_primary(&c), + | ++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs index 9e72c36151e5d..b5f13959081b8 100644 --- a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs +++ b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.rs @@ -11,5 +11,8 @@ impl Foo { field; //~ ERROR cannot find value `field` in this scope Foo { field } //~ ERROR cannot find value `field` in this scope } + fn clone(&self) -> Foo { + Foo { field } //~ ERROR cannot find value `field` in this scope + } } fn main() {} diff --git a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr index 2eb3861e5f11b..3c44c1c249ce2 100644 --- a/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr +++ b/tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr @@ -1,21 +1,41 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9 | +LL | field: u32, + | ---------- a field by that name exists in `Self` +... LL | fn field(&self) -> u32 { | ----- a method by that name is available on `Self` here ... LL | field; - | ^^^^^ a field by this name exists in `Self` + | ^^^^^ error[E0425]: cannot find value `field` in this scope --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15 | +LL | field: u32, + | ---------- a field by that name exists in `Self` +... LL | fn field(&self) -> u32 { | ----- a method by that name is available on `Self` here ... LL | Foo { field } - | ^^^^^ a field by this name exists in `Self` + | ^^^^^ + +error[E0425]: cannot find value `field` in this scope + --> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:15:15 + | +LL | fn field(&self) -> u32 { + | ----- a method by that name is available on `Self` here +... +LL | Foo { field } + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | Foo { field: self.field } + | ++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-14254.stderr b/tests/ui/resolve/issue-14254.stderr index 690a40f7edd77..9284b4babc50f 100644 --- a/tests/ui/resolve/issue-14254.stderr +++ b/tests/ui/resolve/issue-14254.stderr @@ -8,13 +8,23 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:30:9 | LL | x; - | ^ help: you might have meant to use the available field: `self.x` + | ^ + | +help: you might have meant to use the available field + | +LL | self.x; + | +++++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:32:9 | LL | y; - | ^ help: you might have meant to use the available field: `self.y` + | ^ + | +help: you might have meant to use the available field + | +LL | self.y; + | +++++ error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:34:9 @@ -31,7 +41,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:38:9 @@ -43,13 +53,23 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:47:9 | LL | x; - | ^ help: you might have meant to use the available field: `self.x` + | ^ + | +help: you might have meant to use the available field + | +LL | self.x; + | +++++ error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:49:9 | LL | y; - | ^ help: you might have meant to use the available field: `self.y` + | ^ + | +help: you might have meant to use the available field + | +LL | self.y; + | +++++ error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:51:9 @@ -66,7 +86,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:55:9 @@ -83,7 +103,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:73:9 @@ -94,7 +114,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:82:9 @@ -105,7 +125,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:91:9 @@ -116,7 +136,7 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:100:9 @@ -127,55 +147,95 @@ LL | bah; help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:19:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:28:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:45:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:62:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:71:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:80:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:89:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:98:9 | LL | baz(); - | ^^^ help: you might have meant to call the method: `self.baz` + | ^^^ + | +help: you might have meant to call the method + | +LL | self.baz(); + | +++++ error: aborting due to 24 previous errors diff --git a/tests/ui/resolve/issue-2356.stderr b/tests/ui/resolve/issue-2356.stderr index 273e8b2a661fb..5f75ae988702f 100644 --- a/tests/ui/resolve/issue-2356.stderr +++ b/tests/ui/resolve/issue-2356.stderr @@ -1,8 +1,11 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:39:5 | +LL | whiskers: isize, + | --------------- a field by that name exists in `Self` +... LL | whiskers -= other; - | ^^^^^^^^ a field by this name exists in `Self` + | ^^^^^^^^ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 @@ -21,13 +24,21 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:79:5 | LL | whiskers = 0; - | ^^^^^^^^ help: you might have meant to use the available field: `self.whiskers` + | ^^^^^^^^ + | +help: you might have meant to use the available field + | +LL | self.whiskers = 0; + | +++++ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:84:5 | +LL | whiskers: isize, + | --------------- a field by that name exists in `Self` +... LL | whiskers = 4; - | ^^^^^^^^ a field by this name exists in `Self` + | ^^^^^^^^ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 @@ -47,19 +58,34 @@ error[E0425]: cannot find function `clone` in this scope --> $DIR/issue-2356.rs:24:5 | LL | clone(); - | ^^^^^ help: you might have meant to call the method: `self.clone` + | ^^^^^ + | +help: you might have meant to call the method + | +LL | self.clone(); + | +++++ error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:31:5 | LL | default(); - | ^^^^^^^ help: you might have meant to call the associated function: `Self::default` + | ^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | Self::default(); + | ++++++ error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:41:5 | LL | shave(4); - | ^^^^^ help: you might have meant to call the associated function: `Self::shave` + | ^^^^^ + | +help: you might have meant to call the associated function + | +LL | Self::shave(4); + | ++++++ error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:43:5 diff --git a/tests/ui/resolve/issue-60057.stderr b/tests/ui/resolve/issue-60057.stderr index 4d915fcd9fe3d..a2ab86443536c 100644 --- a/tests/ui/resolve/issue-60057.stderr +++ b/tests/ui/resolve/issue-60057.stderr @@ -1,14 +1,22 @@ error[E0425]: cannot find value `banana` in this scope --> $DIR/issue-60057.rs:8:21 | +LL | banana: u8, + | ---------- a field by that name exists in `Self` +... LL | banana: banana - | ^^^^^^ a field by this name exists in `Self` + | ^^^^^^ error[E0425]: cannot find value `banana` in this scope --> $DIR/issue-60057.rs:14:21 | LL | banana: banana - | ^^^^^^ help: you might have meant to use the available field: `self.banana` + | ^^^^^^ + | +help: you might have meant to use the available field + | +LL | banana: self.banana + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/resolve-assoc-suggestions.stderr b/tests/ui/resolve/resolve-assoc-suggestions.stderr index 8def9aa20253b..3d9d4ffaa10c8 100644 --- a/tests/ui/resolve/resolve-assoc-suggestions.stderr +++ b/tests/ui/resolve/resolve-assoc-suggestions.stderr @@ -14,13 +14,23 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:20:9 | LL | field; - | ^^^^^ help: you might have meant to use the available field: `self.field` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.field; + | +++++ error[E0412]: cannot find type `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:23:16 | LL | let _: Type; - | ^^^^ help: you might have meant to use the associated type: `Self::Type` + | ^^^^ + | +help: you might have meant to use the associated type + | +LL | let _: Self::Type; + | ++++++ error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:25:13 @@ -50,7 +60,12 @@ error[E0425]: cannot find value `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:34:9 | LL | method; - | ^^^^^^ help: you might have meant to refer to the method: `self.method` + | ^^^^^^ + | +help: you might have meant to refer to the method + | +LL | self.method; + | +++++ error: aborting due to 9 previous errors diff --git a/tests/ui/resolve/resolve-speculative-adjustment.stderr b/tests/ui/resolve/resolve-speculative-adjustment.stderr index be11a7ebeca00..fb15472bdae8d 100644 --- a/tests/ui/resolve/resolve-speculative-adjustment.stderr +++ b/tests/ui/resolve/resolve-speculative-adjustment.stderr @@ -8,13 +8,23 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:23:9 | LL | field; - | ^^^^^ help: you might have meant to use the available field: `self.field` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.field; + | +++++ error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:25:9 | LL | method(); - | ^^^^^^ help: you might have meant to call the method: `self.method` + | ^^^^^^ + | +help: you might have meant to call the method + | +LL | self.method(); + | +++++ error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:19:13 diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr index f32e0404e46cb..0306c8af87d85 100644 --- a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -1,20 +1,20 @@ error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16 | +LL | config: String, + | -------------- a field by that name exists in `Self` +... LL | Self { config } - | ^^^^^^ - | | - | a field by this name exists in `Self` - | help: a local variable with a similar name exists: `cofig` + | ^^^^^^ help: a local variable with a similar name exists: `cofig` error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20 | +LL | config: String, + | -------------- a field by that name exists in `Self` +... LL | println!("{config}"); - | ^^^^^^ - | | - | a field by this name exists in `Self` - | help: a local variable with a similar name exists: `cofig` + | ^^^^^^ help: a local variable with a similar name exists: `cofig` error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20 @@ -25,7 +25,7 @@ LL | println!("{config}"); help: you might have meant to use the available field | LL | println!("{self.config}"); - | ~~~~~~~~~~~ + | +++++ help: a local variable with a similar name exists | LL | println!("{cofig}"); @@ -43,7 +43,7 @@ LL | fn ba() {} help: you might have meant to refer to the associated function | LL | Self::bah; - | ~~~~~~~~~ + | ++++++ help: a function with a similar name exists | LL | ba; @@ -61,7 +61,7 @@ LL | const BARR: u32 = 3; help: you might have meant to use the associated `const` | LL | Self::BAR; - | ~~~~~~~~~ + | ++++++ help: a constant with a similar name exists | LL | BARR; @@ -79,7 +79,7 @@ LL | type Bar = String; help: you might have meant to use the associated type | LL | let foo: Self::Baz = "".to_string(); - | ~~~~~~~~~ + | ++++++ help: a type alias with a similar name exists | LL | let foo: Bar = "".to_string(); @@ -97,7 +97,7 @@ LL | fn ba() {} help: you might have meant to call the method | LL | self.baz(); - | ~~~~~~~~ + | +++++ help: a function with a similar name exists | LL | ba(); diff --git a/tests/ui/resolve/unresolved_static_type_field.stderr b/tests/ui/resolve/unresolved_static_type_field.stderr index 06926b53ddd35..035dc9b9656ad 100644 --- a/tests/ui/resolve/unresolved_static_type_field.stderr +++ b/tests/ui/resolve/unresolved_static_type_field.stderr @@ -1,8 +1,11 @@ error[E0425]: cannot find value `cx` in this scope --> $DIR/unresolved_static_type_field.rs:9:11 | +LL | cx: bool, + | -------- a field by that name exists in `Self` +... LL | f(cx); - | ^^ a field by this name exists in `Self` + | ^^ error: aborting due to previous error diff --git a/tests/ui/self/class-missing-self.stderr b/tests/ui/self/class-missing-self.stderr index 08493b4f9a2da..ca7a896200fc3 100644 --- a/tests/ui/self/class-missing-self.stderr +++ b/tests/ui/self/class-missing-self.stderr @@ -2,7 +2,12 @@ error[E0425]: cannot find value `meows` in this scope --> $DIR/class-missing-self.rs:9:7 | LL | meows += 1; - | ^^^^^ help: you might have meant to use the available field: `self.meows` + | ^^^^^ + | +help: you might have meant to use the available field + | +LL | self.meows += 1; + | +++++ error[E0425]: cannot find function `sleep` in this scope --> $DIR/class-missing-self.rs:10:7 diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index 0ff2203ec722e..6ba93e46f75e6 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -1,6 +1,7 @@ // build-fail -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics, rustc_attrs, adt_const_params)] +#![allow(incomplete_features)] #[repr(simd)] #[derive(Copy, Clone)] @@ -35,6 +36,7 @@ extern "platform-intrinsic" { fn simd_extract(x: T, idx: u32) -> E; fn simd_shuffle(x: T, y: T, idx: I) -> U; + fn simd_shuffle_generic(x: T, y: T) -> U; } fn main() { @@ -71,5 +73,29 @@ fn main() { //~^ ERROR expected return type of length 4, found `i32x8` with length 8 simd_shuffle::<_, _, i32x2>(x, x, IDX8); //~^ ERROR expected return type of length 8, found `i32x2` with length 2 + + const I2: &[u32] = &[0; 2]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const I4: &[u32] = &[0; 4]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const I8: &[u32] = &[0; 8]; + simd_shuffle_generic::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + simd_shuffle_generic::<_, f32x2, I2>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + simd_shuffle_generic::<_, f32x4, I4>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + simd_shuffle_generic::<_, f32x8, I8>(x, x); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + + simd_shuffle_generic::<_, i32x8, I2>(x, x); + //~^ ERROR expected return type of length 2, found `i32x8` with length 8 + simd_shuffle_generic::<_, i32x8, I4>(x, x); + //~^ ERROR expected return type of length 4, found `i32x8` with length 8 + simd_shuffle_generic::<_, i32x2, I8>(x, x); + //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } } diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index 115d9d4b3f3ac..26e01344939cc 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,75 +1,129 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:44:9 + --> $DIR/generic-elements.rs:46:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:48:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:50:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:52:9 + --> $DIR/generic-elements.rs:54:9 | LL | simd_shuffle::(0, 0, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:55:9 + --> $DIR/generic-elements.rs:57:9 | LL | simd_shuffle::(0, 0, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:58:9 + --> $DIR/generic-elements.rs:60:9 | LL | simd_shuffle::(0, 0, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:61:9 + --> $DIR/generic-elements.rs:63:9 | LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:63:9 + --> $DIR/generic-elements.rs:65:9 | LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:65:9 + --> $DIR/generic-elements.rs:67:9 | LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:68:9 + --> $DIR/generic-elements.rs:70:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:70:9 + --> $DIR/generic-elements.rs:72:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:72:9 + --> $DIR/generic-elements.rs:74:9 | LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:78:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:81:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:84:9 + | +LL | simd_shuffle_generic::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + --> $DIR/generic-elements.rs:87:9 + | +LL | simd_shuffle_generic::<_, f32x2, I2>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + --> $DIR/generic-elements.rs:89:9 + | +LL | simd_shuffle_generic::<_, f32x4, I4>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + --> $DIR/generic-elements.rs:91:9 + | +LL | simd_shuffle_generic::<_, f32x8, I8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:94:9 + | +LL | simd_shuffle_generic::<_, i32x8, I2>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:96:9 + | +LL | simd_shuffle_generic::<_, i32x8, I4>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2 + --> $DIR/generic-elements.rs:98:9 + | +LL | simd_shuffle_generic::<_, i32x2, I8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr new file mode 100644 index 0000000000000..fc66b195674c6 --- /dev/null +++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr @@ -0,0 +1,12 @@ +error: overly complex generic constant + --> $DIR/monomorphize-shuffle-index.rs:29:45 + | +LL | return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); + | ^^--------^^ + | | + | pointer casts are not allowed in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: aborting due to previous error + diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index 2467baa08b0a7..db7953f06dd46 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -1,8 +1,14 @@ -//run-pass -#![feature(repr_simd, platform_intrinsics)] +//[old]run-pass +//[generic_with_fn]run-pass +// revisions: old generic generic_with_fn +#![feature(repr_simd, platform_intrinsics, adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] extern "platform-intrinsic" { + #[cfg(old)] fn simd_shuffle(a: T, b: T, i: I) -> U; + #[cfg(any(generic, generic_with_fn))] + fn simd_shuffle_generic(a: T, b: T) -> U; } #[derive(Copy, Clone)] @@ -11,12 +17,24 @@ struct Simd([T; N]); trait Shuffle { const I: [u32; N]; - - unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd { - simd_shuffle(a, b, Self::I) + const J: &'static [u32] = &Self::I; + + unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd + where + Thing<{ Self::J }>:, + { + #[cfg(old)] + return simd_shuffle(a, b, Self::I); + #[cfg(generic)] + return simd_shuffle_generic::<_, _, { &Self::I }>(a, b); + //[generic]~^ overly complex generic constant + #[cfg(generic_with_fn)] + return simd_shuffle_generic::<_, _, { Self::J }>(a, b); } } +struct Thing; + fn main() { struct I1; impl Shuffle<4> for I1 { diff --git a/tests/ui/suggestions/assoc-type-in-method-return.stderr b/tests/ui/suggestions/assoc-type-in-method-return.stderr index 202e4a16eada7..df3828ad411e1 100644 --- a/tests/ui/suggestions/assoc-type-in-method-return.stderr +++ b/tests/ui/suggestions/assoc-type-in-method-return.stderr @@ -2,7 +2,12 @@ error[E0412]: cannot find type `Bla` in this scope --> $DIR/assoc-type-in-method-return.rs:3:25 | LL | fn to_bla(&self) -> Bla; - | ^^^ help: you might have meant to use the associated type: `Self::Bla` + | ^^^ + | +help: you might have meant to use the associated type + | +LL | fn to_bla(&self) -> Self::Bla; + | ++++++ error: aborting due to previous error diff --git a/tests/ui/suggestions/auxiliary/extern-issue-98562.rs b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs new file mode 100644 index 0000000000000..948e40549c6db --- /dev/null +++ b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs @@ -0,0 +1,26 @@ +pub trait TraitE { + type I3; +} + +pub trait TraitD { + type I3; +} + +pub trait TraitC { + type I1; + type I2; +} + +pub trait TraitB { + type Item; +} + +pub trait TraitA { + fn baz< + U: TraitC + TraitD + TraitE, + V: TraitD + >(_: U, _: V) -> Self + where + U: TraitB, + ::Item: Copy; +} diff --git a/tests/ui/suggestions/issue-98562.rs b/tests/ui/suggestions/issue-98562.rs new file mode 100644 index 0000000000000..de04050d59312 --- /dev/null +++ b/tests/ui/suggestions/issue-98562.rs @@ -0,0 +1,12 @@ +// aux-build:extern-issue-98562.rs + +extern crate extern_issue_98562; +use extern_issue_98562::TraitA; + +struct X; +impl TraitA for X { + //~^ ERROR not all trait items implemented +} +//~^ HELP implement the missing item: `fn baz + TraitD, V: TraitD>(_: U, _: V) -> Self where U: TraitE, U: TraitB, ::Item: Copy { todo!() }` + +fn main() {} diff --git a/tests/ui/suggestions/issue-98562.stderr b/tests/ui/suggestions/issue-98562.stderr new file mode 100644 index 0000000000000..7897fa441a24f --- /dev/null +++ b/tests/ui/suggestions/issue-98562.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `baz` + --> $DIR/issue-98562.rs:7:1 + | +LL | impl TraitA for X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `baz` in implementation + | + = help: implement the missing item: `fn baz + TraitD, V: TraitD>(_: U, _: V) -> Self where U: TraitE, U: TraitB, ::Item: Copy { todo!() }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr index 77fa956287816..84cb6e98553ee 100644 --- a/tests/ui/suggestions/missing-assoc-fn.stderr +++ b/tests/ui/suggestions/missing-assoc-fn.stderr @@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter` LL | impl FromIterator<()> for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation | - = help: implement the missing item: `fn from_iter(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = () { todo!() }` + = help: implement the missing item: `fn from_iter>(_: T) -> Self { todo!() }` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs new file mode 100644 index 0000000000000..2790639234060 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.rs @@ -0,0 +1,53 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs)] + +// Check that we correctly rerun the trait solver for heads of cycles, +// even if they are not the root. + +struct A(*const T); +struct B(*const T); +struct C(*const T); + +#[rustc_coinductive] +trait Trait<'a, 'b> {} +trait NotImplemented {} + +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for A where B: Trait<'a, 'b> {} + +// With this the root of `B` is `A`, even if the other impl does +// not have a cycle with `A`. This candidate never applies because of +// the `A: NotImplemented` bound. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B +where + A: Trait<'a, 'b>, + A: NotImplemented, +{ +} + +// This impl directly requires 'b to be equal to 'static. +// +// Because of the coinductive cycle through `C` it also requires +// 'a to be 'static. +impl<'a, T: ?Sized> Trait<'a, 'static> for B +where + C: Trait<'a, 'a>, +{} + +// In the first iteration of `B: Trait<'a, 'b>` we don't add any +// constraints here, only after setting the provisional result to require +// `'b == 'static` do we also add that constraint for `'a`. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for C +where + B: Trait<'a, 'b>, +{} + +fn impls_trait<'a, 'b, T: Trait<'a, 'b> + ?Sized>() {} + +fn check<'a, T: ?Sized>() { + impls_trait::<'a, 'static, A>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { + check::<()>(); +} diff --git a/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr new file mode 100644 index 0000000000000..4cbd0898148a5 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:47:5 + | +LL | fn check<'a, T: ?Sized>() { + | -- lifetime `'a` defined here +LL | impls_trait::<'a, 'static, A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs index 3cfe7ab87f60a..f06b98a79cfe3 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs @@ -39,7 +39,7 @@ fn impls_ar() {} fn main() { impls_a::<()>(); - // FIXME(-Ztrait-solver=next): This is broken and should error. + //~^ ERROR overflow evaluating the requirement `(): A` impls_ar::<()>(); //~^ ERROR overflow evaluating the requirement `(): AR` diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr index 341153340635e..859b3f3f1c7d7 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr @@ -1,3 +1,16 @@ +error[E0275]: overflow evaluating the requirement `(): A` + --> $DIR/inductive-not-on-stack.rs:41:15 + | +LL | impls_a::<()>(); + | ^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_not_on_stack`) +note: required by a bound in `impls_a` + --> $DIR/inductive-not-on-stack.rs:25:15 + | +LL | fn impls_a() {} + | ^ required by this bound in `impls_a` + error[E0275]: overflow evaluating the requirement `(): AR` --> $DIR/inductive-not-on-stack.rs:44:16 | @@ -11,6 +24,6 @@ note: required by a bound in `impls_ar` LL | fn impls_ar() {} | ^^ required by this bound in `impls_ar` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs index 9a50c0f988a56..31fea42fa5d8a 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -1,5 +1,5 @@ // compile-flags: --edition=2021 -// check-pass +// build-pass #![feature(type_alias_impl_trait)] fn main() { diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs new file mode 100644 index 0000000000000..7c2d68cceb8fc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs @@ -0,0 +1,19 @@ +// build-pass +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +pub struct Foo { + /// This type must have nontrivial drop glue + field: String, +} + +pub type Tait = impl Sized; + +pub async fn ice_cold(beverage: Tait) { + // Must destructure at least one field of `Foo` + let Foo { field } = beverage; + _ = field; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs new file mode 100644 index 0000000000000..8568b26bea2a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructure_tait-layout_of-ice-113594.rs @@ -0,0 +1,23 @@ +// build-pass +// edition: 2021 + +#![feature(type_alias_impl_trait)] + +fn foo(x: T) { + type Opaque = impl Sized; + let foo: Opaque = (x,); + let (a,): (T,) = foo; +} + +const fn bar(x: T) { + type Opaque = impl Copy; + let foo: Opaque = (x, 2u32); + let (a, b): (T, u32) = foo; +} + +fn main() { + foo::(1); + bar::(1); + const CONST: () = bar::(42u32); + CONST +} diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr index 3312230bc81df..2063becdb0838 100644 --- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr +++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr @@ -1,6 +1,5 @@ error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}` | - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit`... = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}>`... = note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:15:31: 17:2}`... @@ -8,7 +7,11 @@ error[E0391]: cycle detected when computing layout of `{async block@$DIR/indirec = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}>`... = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:23:9: 23:42}`, completing the cycle - = note: cycle used when computing layout of `::Recur` +note: cycle used when elaborating drops for `::recur` + --> $DIR/indirect-recursion-issue-112047.rs:22:5 + | +LL | fn recur(self) -> Self::Recur { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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: aborting due to previous error