diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 9ddadcf16aa3d..a643a91141e19 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -384,15 +384,19 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); - // Default to Intel syntax on x86 - let intel_syntax = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) - && !options.contains(InlineAsmOptions::ATT_SYNTAX); - // Build the template string let mut template_str = String::new(); - if intel_syntax { - template_str.push_str(".intel_syntax\n"); + + // On X86 platforms there are two assembly syntaxes. Rust uses intel by default, + // but AT&T can be specified explicitly. + if matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) { + if options.contains(InlineAsmOptions::ATT_SYNTAX) { + template_str.push_str(".att_syntax\n") + } else { + template_str.push_str(".intel_syntax\n") + } } + for piece in template { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), @@ -431,7 +435,11 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { } } } - if intel_syntax { + + // Just to play it safe, if intel was used, reset the assembly syntax to att. + if matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) + && !options.contains(InlineAsmOptions::ATT_SYNTAX) + { template_str.push_str("\n.att_syntax\n"); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 91ada856d5977..b9dd10ff014fe 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1980,12 +1980,12 @@ unsafe extern "C" { pub(crate) fn LLVMRustBuildMinNum<'a>( B: &Builder<'a>, LHS: &'a Value, - LHS: &'a Value, + RHS: &'a Value, ) -> &'a Value; pub(crate) fn LLVMRustBuildMaxNum<'a>( B: &Builder<'a>, LHS: &'a Value, - LHS: &'a Value, + RHS: &'a Value, ) -> &'a Value; // Atomic Operations diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 1896f63bd2d62..e0a3ad55be08a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -800,9 +800,7 @@ impl<'a> Linker for GccLinker<'a> { return; } - let is_windows = self.sess.target.is_like_windows; - let path = tmpdir.join(if is_windows { "list.def" } else { "list" }); - + let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" }); debug!("EXPORTED SYMBOLS:"); if self.sess.target.is_like_darwin { @@ -817,7 +815,8 @@ impl<'a> Linker for GccLinker<'a> { if let Err(error) = res { self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error }); } - } else if is_windows { + self.link_arg("-exported_symbols_list").link_arg(path); + } else if self.sess.target.is_like_windows { let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; @@ -835,6 +834,21 @@ impl<'a> Linker for GccLinker<'a> { if let Err(error) = res { self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error }); } + self.link_arg(path); + } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris { + let res: io::Result<()> = try { + let mut f = File::create_buffered(&path)?; + writeln!(f, "{{")?; + for (sym, _) in symbols { + debug!(sym); + writeln!(f, " {sym};")?; + } + writeln!(f, "}};")?; + }; + if let Err(error) = res { + self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); + } + self.link_arg("--dynamic-list").link_arg(path); } else { // Write an LD version script let res: io::Result<()> = try { @@ -852,18 +866,13 @@ impl<'a> Linker for GccLinker<'a> { if let Err(error) = res { self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); } - } - - if self.sess.target.is_like_darwin { - self.link_arg("-exported_symbols_list").link_arg(path); - } else if self.sess.target.is_like_solaris { - self.link_arg("-M").link_arg(path); - } else if is_windows { - self.link_arg(path); - } else { - let mut arg = OsString::from("--version-script="); - arg.push(path); - self.link_arg(arg).link_arg("--no-undefined-version"); + if self.sess.target.is_like_solaris { + self.link_arg("-M").link_arg(path); + } else { + let mut arg = OsString::from("--version-script="); + arg.push(path); + self.link_arg(arg).link_arg("--no-undefined-version"); + } } } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index c21b16c9f9f04..bac4d70103c3d 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -82,13 +82,6 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to -> hir_typeck_const_continue_bad_label = `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` -hir_typeck_const_select_must_be_const = this argument must be a `const fn` - .help = consult the documentation on `const_eval_select` for more information - -hir_typeck_const_select_must_be_fn = this argument must be a function item - .note = expected a function item, found {$ty} - .help = consult the documentation on `const_eval_select` for more information - hir_typeck_continue_labeled_block = `continue` pointing to a labeled block .label = labeled blocks cannot be `continue`'d diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 7611f8ac3e1a7..48bb45de53eb4 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -578,29 +578,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let Some(def_id) = def_id - && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn - && self.tcx.is_intrinsic(def_id, sym::const_eval_select) - { - let fn_sig = self.resolve_vars_if_possible(fn_sig); - for idx in 0..=1 { - let arg_ty = fn_sig.inputs()[idx + 1]; - let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span); - // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that - // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed - // in the function signature (`F: FnOnce`), so I did not bother to add another check here. - // - // This check is here because there is currently no way to express a trait bound for `FnDef` types only. - if let ty::FnDef(def_id, _args) = *arg_ty.kind() { - if idx == 0 && !self.tcx.is_const_fn(def_id) { - self.dcx().emit_err(errors::ConstSelectMustBeConst { span }); - } - } else { - self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty }); - } - } - } - fn_sig.output() } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3606c778fc407..a8bb6956f1016 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -605,24 +605,6 @@ impl Subdiagnostic for RemoveSemiForCoerce { } } -#[derive(Diagnostic)] -#[diag(hir_typeck_const_select_must_be_const)] -#[help] -pub(crate) struct ConstSelectMustBeConst { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_typeck_const_select_must_be_fn)] -#[note] -#[help] -pub(crate) struct ConstSelectMustBeFn<'a> { - #[primary_span] - pub span: Span, - pub ty: Ty<'a>, -} - #[derive(Diagnostic)] #[diag(hir_typeck_union_pat_multiple_fields)] pub(crate) struct UnionPatMultipleFields { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 982cfa2e42be4..be774106abf8f 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // process any deferred resolutions. let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id); for deferred_call_resolution in deferred_call_resolutions { - deferred_call_resolution.resolve(self); + deferred_call_resolution.resolve(&mut FnCtxt::new( + self, + self.param_env, + closure_def_id, + )); } } diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 176d308de9139..d694a092853af 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -1,7 +1,8 @@ use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::traits::{ - ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation, + ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode, + PredicateObligation, }; use rustc_middle::span_bug; use rustc_middle::traits::query::NoSolution; @@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>( ) -> Result>, EvaluationFailure> { match selcx.tcx().as_lang_item(obligation.predicate.def_id()) { Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation), + Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => { + evaluate_host_effect_for_fn_goal(selcx, obligation) + } _ => Err(EvaluationFailure::NoSolution), } } @@ -398,6 +402,51 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>( .collect()) } +// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver. +fn evaluate_host_effect_for_fn_goal<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &HostEffectObligation<'tcx>, +) -> Result>, EvaluationFailure> { + let tcx = selcx.tcx(); + let self_ty = obligation.predicate.self_ty(); + + let (def, args) = match *self_ty.kind() { + ty::FnDef(def, args) => (def, args), + + // We may support function pointers at some point in the future + ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution), + + // Closures could implement `[const] Fn`, + // but they don't really need to right now. + ty::Closure(..) | ty::CoroutineClosure(_, _) => { + return Err(EvaluationFailure::NoSolution); + } + + // Everything else needs explicit impls or cannot have an impl + _ => return Err(EvaluationFailure::NoSolution), + }; + + match tcx.constness(def) { + hir::Constness::Const => Ok(tcx + .const_conditions(def) + .instantiate(tcx, args) + .into_iter() + .map(|(c, span)| { + let code = ObligationCauseCode::WhereClause(def, span); + let cause = + ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code); + Obligation::new( + tcx, + cause, + obligation.param_env, + c.to_host_effect_clause(tcx, obligation.predicate.constness), + ) + }) + .collect()), + hir::Constness::NotConst => Err(EvaluationFailure::NoSolution), + } +} + fn evaluate_host_effect_from_selection_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml index c5446cd76e326..3ccb05f73fb84 100644 --- a/library/compiler-builtins/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/compiler-builtins/Cargo.toml @@ -19,6 +19,8 @@ links = "compiler-rt" bench = false doctest = false test = false +# make sure this crate isn't included in public standard library docs +doc = false [dependencies] core = { path = "../../core", optional = true } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index f5dcfeebed8fa..c2e4b751c65f3 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2279,7 +2279,7 @@ pub const fn const_eval_select( ) -> RET where G: FnOnce, - F: FnOnce; + F: const FnOnce; /// A macro to make it easier to invoke const_eval_select. Use as follows: /// ```rust,ignore (just a macro example) diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index df48c104410ca..763b60d88e510 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -72,7 +72,8 @@ use crate::marker::Tuple; )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(const_trait_impl) #[const_trait] +#[const_trait] +#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] pub trait Fn: FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -159,7 +160,8 @@ pub trait Fn: FnMut { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(const_trait_impl) #[const_trait] +#[const_trait] +#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] pub trait FnMut: FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] @@ -238,7 +240,8 @@ pub trait FnMut: FnOnce { )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -// FIXME(const_trait_impl) #[const_trait] +#[const_trait] +#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] @@ -254,9 +257,10 @@ mod impls { use crate::marker::Tuple; #[stable(feature = "rust1", since = "1.0.0")] - impl Fn for &F + #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] + impl const Fn for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -264,9 +268,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &F + #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] + impl const FnMut for &F where - F: Fn, + F: ~const Fn, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -274,9 +279,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &F + #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] + impl const FnOnce for &F where - F: Fn, + F: ~const Fn, { type Output = F::Output; @@ -286,9 +292,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &mut F + #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] + impl const FnMut for &mut F where - F: FnMut, + F: ~const FnMut, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -296,9 +303,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &mut F + #[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] + impl const FnOnce for &mut F where - F: FnMut, + F: ~const FnMut, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 003ac4f0cd37f..668e988abff39 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -61,6 +61,7 @@ struct Exception { // and its destructor is executed by the C++ runtime. When we take the Box // out of the exception, we need to leave the exception in a valid state // for its destructor to run without double-dropping the Box. + // We also construct this as None for copies of the exception. data: Option>, } @@ -264,7 +265,11 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { // runtime under a try/catch block and the panic that we generate here will be // used as the result of the exception copy. This is used by the C++ runtime to // support capturing exceptions with std::exception_ptr, which we can't support -// because Box isn't clonable. +// because Box isn't clonable. Thus we throw an exception without data, +// which the C++ runtime will attempt to copy, which will once again fail, and +// a std::bad_exception instance ends up in the std::exception_ptr instance. +// The lack of data doesn't matter because the exception will never be rethrown +// - it is purely used to signal to the C++ runtime that copying failed. macro_rules! define_cleanup { ($abi:tt $abi2:tt) => { unsafe extern $abi fn exception_cleanup(e: *mut Exception) { @@ -278,7 +283,9 @@ macro_rules! define_cleanup { unsafe extern $abi2 fn exception_copy( _dest: *mut Exception, _src: *mut Exception ) -> *mut Exception { - panic!("Rust panics cannot be copied"); + unsafe { + throw_exception(None); + } } } } @@ -291,6 +298,10 @@ cfg_if::cfg_if! { } pub(crate) unsafe fn panic(data: Box) -> u32 { + unsafe { throw_exception(Some(data)) } +} + +unsafe fn throw_exception(data: Option>) -> ! { use core::intrinsics::{AtomicOrdering, atomic_store}; // _CxxThrowException executes entirely on this stack frame, so there's no @@ -300,8 +311,7 @@ pub(crate) unsafe fn panic(data: Box) -> u32 { // The ManuallyDrop is needed here since we don't want Exception to be // dropped when unwinding. Instead it will be dropped by exception_cleanup // which is invoked by the C++ runtime. - let mut exception = - ManuallyDrop::new(Exception { canary: (&raw const TYPE_DESCRIPTOR), data: Some(data) }); + let mut exception = ManuallyDrop::new(Exception { canary: (&raw const TYPE_DESCRIPTOR), data }); let throw_ptr = (&raw mut exception) as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index c4937c36d4c9c..290c2eeed44c6 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -5,6 +5,10 @@ name = "sysroot" version = "0.0.0" edition = "2024" +[lib] +# make sure this crate isn't included in public standard library docs +doc = false + # this is a dummy crate to ensure that all required crates appear in the sysroot [dependencies] proc_macro = { path = "../proc_macro", public = true } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 0587d21ecc28d..b721911de7ea7 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -449,26 +449,24 @@ fn copy_self_contained_objects( target_deps } -/// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.). +/// Resolves standard library crates for `Std::run_make` for any build kind (like check, doc, +/// build, clippy, etc.). pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec { - // FIXME: Extend builder tests to cover the `crates` field of `Std` instances. - if cfg!(test) { - return vec![]; - } - - let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library")); + let mut crates = run.make_run_crates(builder::Alias::Library); + + // For no_std targets, we only want to check core and alloc + // Regardless of core/alloc being selected explicitly or via the "library" default alias, + // we only want to keep these two crates. + // The set of no_std crates should be kept in sync with what `Builder::std_cargo` does. + // Note: an alternative design would be to return an enum from this function (Default vs Subset) + // of crates. However, several steps currently pass `-p ` even if all crates are + // selected, because Cargo behaves differently in that case. To keep that behavior without + // making further changes, we pre-filter the no-std crates here. let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false); - - // For no_std targets, do not add any additional crates to the compilation other than what `compile::std_cargo` already adds for no_std targets. if target_is_no_std { - vec![] - } - // If the paths include "library", build the entire standard library. - else if has_alias { - run.make_run_crates(builder::Alias::Library) - } else { - run.cargo_crates_in_set() + crates.retain(|c| c == "core" || c == "alloc"); } + crates } /// Tries to find LLVM's `compiler-rt` source directory, for building `library/profiler_builtins`. diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index f7c4c5ad0bbd3..37418f640aca6 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -665,7 +665,11 @@ impl Step for Std { } fn metadata(&self) -> Option { - Some(StepMetadata::doc("std", self.target).stage(self.stage)) + Some( + StepMetadata::doc("std", self.target) + .stage(self.stage) + .with_metadata(format!("crates=[{}]", self.crates.join(","))), + ) } } @@ -739,10 +743,6 @@ fn doc_std( } for krate in requested_crates { - if krate == "sysroot" { - // The sysroot crate is an implementation detail, don't include it in public docs. - continue; - } cargo.arg("-p").arg(krate); } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 7464327fde989..4d606953d9986 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -146,6 +146,8 @@ pub struct StepMetadata { target: TargetSelection, built_by: Option, stage: Option, + /// Additional opaque string printed in the metadata + metadata: Option, } impl StepMetadata { @@ -170,7 +172,7 @@ impl StepMetadata { } fn new(name: &'static str, target: TargetSelection, kind: Kind) -> Self { - Self { name, kind, target, built_by: None, stage: None } + Self { name, kind, target, built_by: None, stage: None, metadata: None } } pub fn built_by(mut self, compiler: Compiler) -> Self { @@ -183,6 +185,11 @@ impl StepMetadata { self } + pub fn with_metadata(mut self, metadata: String) -> Self { + self.metadata = Some(metadata); + self + } + pub fn get_stage(&self) -> Option { self.stage.or(self .built_by diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index bbcb58fca14f3..68d1885b0a7d5 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -637,8 +637,8 @@ mod snapshot { use crate::core::build_steps::{compile, dist, doc, test, tool}; use crate::core::builder::tests::{ - TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args, first, - host_target, render_steps, run_build, + RenderConfig, TEST_TRIPLE_1, TEST_TRIPLE_2, TEST_TRIPLE_3, configure, configure_with_args, + first, host_target, render_steps, run_build, }; use crate::core::builder::{Builder, Kind, StepDescription, StepMetadata}; use crate::core::config::TargetSelection; @@ -994,7 +994,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustdoc 0 - [doc] std 1 + [doc] std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] "); } @@ -1043,12 +1043,12 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustdoc 1 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 0 -> RustInstaller 1 [dist] docs - [doc] std 2 + [doc] std 2 crates=[] [dist] mingw [build] rustc 0 -> GenerateCopyright 1 [dist] rustc @@ -1075,12 +1075,12 @@ mod snapshot { [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 [build] rustdoc 1 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 0 -> RustInstaller 1 [dist] docs - [doc] std 2 + [doc] std 2 crates=[] [dist] mingw [build] rustc 0 -> GenerateCopyright 1 [dist] rustc @@ -1112,15 +1112,15 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustdoc 1 - [doc] std 2 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 0 -> RustInstaller 1 [dist] docs [dist] docs - [doc] std 2 - [doc] std 2 + [doc] std 2 crates=[] + [doc] std 2 crates=[] [dist] mingw [dist] mingw [build] rustc 0 -> GenerateCopyright 1 @@ -1149,14 +1149,14 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustdoc 1 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 1 -> std 1 [build] rustc 2 -> std 2 [build] rustc 0 -> RustInstaller 1 [dist] docs - [doc] std 2 + [doc] std 2 crates=[] [dist] mingw [build] rustc 0 -> GenerateCopyright 1 [dist] rustc @@ -1186,8 +1186,8 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustdoc 1 - [doc] std 2 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 1 -> std 1 @@ -1195,8 +1195,8 @@ mod snapshot { [build] rustc 0 -> RustInstaller 1 [dist] docs [dist] docs - [doc] std 2 - [doc] std 2 + [doc] std 2 crates=[] + [doc] std 2 crates=[] [dist] mingw [dist] mingw [build] rustc 0 -> GenerateCopyright 1 @@ -1228,11 +1228,11 @@ mod snapshot { [build] rustc 1 -> std 1 [build] rustc 1 -> rustc 2 [build] rustdoc 1 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 0 -> RustInstaller 1 [dist] docs - [doc] std 2 + [doc] std 2 crates=[] [dist] mingw [build] rustc 2 -> std 2 [dist] rustc 2 -> std 2 @@ -1260,14 +1260,14 @@ mod snapshot { [build] rustc 1 -> rustc 2 [build] rustc 1 -> WasmComponentLd 2 [build] rustdoc 1 - [doc] std 2 + [doc] std 2 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] [build] rustc 2 -> std 2 [build] rustc 1 -> std 1 [build] rustc 2 -> std 2 [build] rustc 0 -> LintDocs 1 [build] rustc 0 -> RustInstaller 1 [dist] docs - [doc] std 2 + [doc] std 2 crates=[] [dist] mingw [build] llvm [build] rustc 1 -> rustc 2 @@ -1575,6 +1575,80 @@ mod snapshot { steps.assert_contains(StepMetadata::test("CrateLibrustc", host)); steps.assert_contains_fuzzy(StepMetadata::build("rustc", host)); } + + #[test] + fn doc_library() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("library") + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind] + "); + } + + #[test] + fn doc_core() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("core") + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 crates=[core] + "); + } + + #[test] + fn doc_core_no_std_target() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("core") + .override_target_no_std(&host_target()) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 crates=[core] + "); + } + + #[test] + fn doc_library_no_std_target() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("library") + .override_target_no_std(&host_target()) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 crates=[alloc,core] + "); + } + + #[test] + fn doc_library_no_std_target_cross_compile() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .path("library") + .targets(&[TEST_TRIPLE_1]) + .override_target_no_std(TEST_TRIPLE_1) + .render_steps(), @r" + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustdoc 0 + [doc] std 1 crates=[alloc,core] + "); + } } struct ExecutedSteps { @@ -1583,7 +1657,11 @@ struct ExecutedSteps { impl ExecutedSteps { fn render(&self) -> String { - render_steps(&self.steps) + self.render_with(RenderConfig::default()) + } + + fn render_with(&self, config: RenderConfig) -> String { + render_steps(&self.steps, config) } #[track_caller] @@ -1592,7 +1670,7 @@ impl ExecutedSteps { if !self.contains(&metadata) { panic!( "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}", - render_metadata(&metadata), + render_metadata(&metadata, &RenderConfig::default()), self.render() ); } @@ -1607,7 +1685,7 @@ impl ExecutedSteps { if !self.contains_fuzzy(&metadata) { panic!( "Metadata `{}` ({metadata:?}) not found in executed steps:\n{}", - render_metadata(&metadata), + render_metadata(&metadata, &RenderConfig::default()), self.render() ); } @@ -1619,7 +1697,7 @@ impl ExecutedSteps { if self.contains(&metadata) { panic!( "Metadata `{}` ({metadata:?}) found in executed steps (it should not be there):\n{}", - render_metadata(&metadata), + render_metadata(&metadata, &RenderConfig::default()), self.render() ); } @@ -1641,7 +1719,7 @@ impl ExecutedSteps { } fn fuzzy_metadata_eq(executed: &StepMetadata, to_match: &StepMetadata) -> bool { - let StepMetadata { name, kind, target, built_by: _, stage: _ } = executed; + let StepMetadata { name, kind, target, built_by: _, stage: _, metadata } = executed; *name == to_match.name && *kind == to_match.kind && *target == to_match.target } @@ -1672,6 +1750,16 @@ impl ConfigBuilder { } } +struct RenderConfig { + normalize_host: bool, +} + +impl Default for RenderConfig { + fn default() -> Self { + Self { normalize_host: true } + } +} + /// Renders the executed bootstrap steps for usage in snapshot tests with insta. /// Only renders certain important steps. /// Each value in `steps` should be a tuple of (Step, step output). @@ -1679,7 +1767,7 @@ impl ConfigBuilder { /// The arrow in the rendered output (`X -> Y`) means `X builds Y`. /// This is similar to the output printed by bootstrap to stdout, but here it is /// generated purely for the purpose of tests. -fn render_steps(steps: &[ExecutedStep]) -> String { +fn render_steps(steps: &[ExecutedStep], config: RenderConfig) -> String { steps .iter() .filter_map(|step| { @@ -1689,32 +1777,35 @@ fn render_steps(steps: &[ExecutedStep]) -> String { return None; }; - Some(render_metadata(&metadata)) + Some(render_metadata(&metadata, &config)) }) .collect::>() .join("\n") } -fn render_metadata(metadata: &StepMetadata) -> String { +fn render_metadata(metadata: &StepMetadata, config: &RenderConfig) -> String { let mut record = format!("[{}] ", metadata.kind.as_str()); if let Some(compiler) = metadata.built_by { - write!(record, "{} -> ", render_compiler(compiler)); + write!(record, "{} -> ", render_compiler(compiler, config)); } let stage = metadata.get_stage().map(|stage| format!("{stage} ")).unwrap_or_default(); - write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target)); + write!(record, "{} {stage}<{}>", metadata.name, normalize_target(metadata.target, config)); + if let Some(metadata) = &metadata.metadata { + write!(record, " {metadata}"); + } record } -fn normalize_target(target: TargetSelection) -> String { - target - .to_string() - .replace(&host_target(), "host") - .replace(TEST_TRIPLE_1, "target1") - .replace(TEST_TRIPLE_2, "target2") +fn normalize_target(target: TargetSelection, config: &RenderConfig) -> String { + let mut target = target.to_string(); + if config.normalize_host { + target = target.replace(&host_target(), "host"); + } + target.replace(TEST_TRIPLE_1, "target1").replace(TEST_TRIPLE_2, "target2") } -fn render_compiler(compiler: Compiler) -> String { - format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host)) +fn render_compiler(compiler: Compiler, config: &RenderConfig) -> String { + format!("rustc {} <{}>", compiler.stage, normalize_target(compiler.host, config)) } fn host_target() -> String { diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs index 5b568c1df5b16..ec87e71e0b6d1 100644 --- a/src/bootstrap/src/utils/tests/mod.rs +++ b/src/bootstrap/src/utils/tests/mod.rs @@ -48,17 +48,30 @@ impl ConfigBuilder { } pub fn path(mut self, path: &str) -> Self { - self.args.push(path.to_string()); - self + self.arg(path) } pub fn paths(mut self, paths: &[&str]) -> Self { - for path in paths { - self = self.path(path); + self.args(paths) + } + + pub fn arg(mut self, arg: &str) -> Self { + self.args.push(arg.to_string()); + self + } + + pub fn args(mut self, args: &[&str]) -> Self { + for arg in args { + self = self.arg(arg); } self } + /// Set the specified target to be treated as a no_std target. + pub fn override_target_no_std(mut self, target: &str) -> Self { + self.args(&["--set", &format!("target.{target}.no-std=true")]) + } + pub fn hosts(mut self, targets: &[&str]) -> Self { self.args.push("--host".to_string()); self.args.push(targets.join(",")); @@ -77,13 +90,6 @@ impl ConfigBuilder { self } - pub fn args(mut self, args: &[&str]) -> Self { - for arg in args { - self.args.push(arg.to_string()); - } - self - } - pub fn create_config(mut self) -> Config { // Run in dry-check, otherwise the test would be too slow self.args.push("--dry-run".to_string()); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 96199cb972a86..37b012d6d0d0c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -152,8 +152,14 @@ pub(crate) fn try_inline( }; cx.inlined.insert(did.into()); - let mut item = - crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None); + let mut item = crate::clean::generate_item_with_correct_attrs( + cx, + kind, + did, + name, + import_def_id.as_slice(), + None, + ); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. item.inner.inline_stmt_id = import_def_id; ret.push(item); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c2f3da18cd302..e6f7aef02c0ec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -94,12 +94,12 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< // This covers the case where somebody does an import which should pull in an item, // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. - items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| { + items.extend(doc.items.values().flat_map(|(item, renamed, import_ids)| { // First, lower everything other than glob imports. if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { return Vec::new(); } - let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id); + let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids); for item in &v { if let Some(name) = item.name && (cx.render_options.document_hidden || !item.is_doc_hidden()) @@ -162,7 +162,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< kind, doc.def_id.to_def_id(), doc.name, - doc.import_id, + doc.import_id.as_slice(), doc.renamed, ) } @@ -182,22 +182,29 @@ fn generate_item_with_correct_attrs( kind: ItemKind, def_id: DefId, name: Symbol, - import_id: Option, + import_ids: &[LocalDefId], renamed: Option, ) -> Item { let target_attrs = inline::load_attrs(cx, def_id); - let attrs = if let Some(import_id) = import_id { - // glob reexports are treated the same as `#[doc(inline)]` items. - // - // For glob re-exports the item may or may not exist to be re-exported (potentially the cfgs - // on the path up until the glob can be removed, and only cfgs on the globbed item itself - // matter), for non-inlined re-exports see #85043. - let is_inline = hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc) - .get_word_attr(sym::inline) - .is_some() - || (is_glob_import(cx.tcx, import_id) - && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id))); - let mut attrs = get_all_import_attributes(cx, import_id, def_id, is_inline); + let attrs = if !import_ids.is_empty() { + let mut attrs = Vec::with_capacity(import_ids.len()); + let mut is_inline = false; + + for import_id in import_ids.iter().copied() { + // glob reexports are treated the same as `#[doc(inline)]` items. + // + // For glob re-exports the item may or may not exist to be re-exported (potentially the + // cfgs on the path up until the glob can be removed, and only cfgs on the globbed item + // itself matter), for non-inlined re-exports see #85043. + let import_is_inline = + hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc) + .get_word_attr(sym::inline) + .is_some() + || (is_glob_import(cx.tcx, import_id) + && (cx.render_options.document_hidden || !cx.tcx.is_doc_hidden(def_id))); + attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); + is_inline = is_inline || import_is_inline; + } add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None); attrs } else { @@ -216,7 +223,8 @@ fn generate_item_with_correct_attrs( let name = renamed.or(Some(name)); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg); - item.inner.inline_stmt_id = import_id; + // FIXME (GuillaumeGomez): Should we also make `inline_stmt_id` a `Vec` instead of an `Option`? + item.inner.inline_stmt_id = import_ids.first().copied(); item } @@ -2754,7 +2762,7 @@ fn clean_maybe_renamed_item<'tcx>( cx: &mut DocContext<'tcx>, item: &hir::Item<'tcx>, renamed: Option, - import_id: Option, + import_ids: &[LocalDefId], ) -> Vec { use hir::ItemKind; fn get_name( @@ -2825,7 +2833,7 @@ fn clean_maybe_renamed_item<'tcx>( })), item.owner_id.def_id.to_def_id(), name, - import_id, + import_ids, renamed, )); return ret; @@ -2880,7 +2888,7 @@ fn clean_maybe_renamed_item<'tcx>( kind, item.owner_id.def_id.to_def_id(), name, - import_id, + import_ids, renamed, )] }) @@ -3151,7 +3159,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( kind, item.owner_id.def_id.to_def_id(), item.ident.name, - import_id, + import_id.as_slice(), renamed, ) }) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 2889bfae7b000..2784d7c761a84 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -32,11 +32,29 @@ pub(crate) struct Module<'hir> { pub(crate) def_id: LocalDefId, pub(crate) renamed: Option, pub(crate) import_id: Option, - /// The key is the item `ItemId` and the value is: (item, renamed, import_id). + /// The key is the item `ItemId` and the value is: (item, renamed, Vec). /// We use `FxIndexMap` to keep the insert order. + /// + /// `import_id` needs to be a `Vec` because we live in a dark world where you can have code + /// like: + /// + /// ``` + /// mod raw { + /// pub fn foo() {} + /// } + /// + /// /// Foobar + /// pub use raw::foo; + /// + /// pub use raw::*; + /// ``` + /// + /// So in this case, we don't want to have two items but just one with attributes from all + /// non-glob imports to be merged. Glob imports attributes are always ignored, whether they're + /// shadowed or not. pub(crate) items: FxIndexMap< (LocalDefId, Option), - (&'hir hir::Item<'hir>, Option, Option), + (&'hir hir::Item<'hir>, Option, Vec), >, /// (def_id, renamed) -> (res, local_import_id) @@ -154,7 +172,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { { let item = self.cx.tcx.hir_expect_item(local_def_id); let (ident, _, _) = item.expect_macro(); - top_level_module.items.insert((local_def_id, Some(ident.name)), (item, None, None)); + top_level_module + .items + .insert((local_def_id, Some(ident.name)), (item, None, Vec::new())); } } @@ -236,7 +256,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ) -> bool { debug!("maybe_inline_local (renamed: {renamed:?}) res: {res:?}"); - let glob = renamed.is_none(); if renamed == Some(kw::Underscore) { // We never inline `_` reexports. return false; @@ -261,6 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } + let is_glob = renamed.is_none(); let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did); let Some(res_did) = ori_res_did.as_local() else { // For cross-crate impl inlining we need to know whether items are @@ -268,7 +288,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // made reachable by cross-crate inlining which we're checking here. // (this is done here because we need to know this upfront). crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did); - if is_hidden || glob { + if is_hidden || is_glob { return false; } // We store inlined foreign items otherwise, it'd mean that the `use` item would be kept @@ -316,10 +336,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // Bang macros are handled a bit on their because of how they are handled by the // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have // `#[doc(inline)]`, then we don't inline it. - Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { + Node::Item(_) if is_bang_macro && !please_inline && !is_glob && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if is_glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir_item(i); @@ -328,13 +348,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.inlining = prev; true } - Node::Item(it) if !glob => { + Node::Item(it) if !is_glob => { let prev = mem::replace(&mut self.inlining, true); self.visit_item_inner(it, renamed, Some(def_id)); self.inlining = prev; true } - Node::ForeignItem(it) if !glob => { + Node::ForeignItem(it) if !is_glob => { let prev = mem::replace(&mut self.inlining, true); self.visit_foreign_item_inner(it, renamed, Some(def_id)); self.inlining = prev; @@ -378,8 +398,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn add_to_current_mod( &mut self, item: &'tcx hir::Item<'_>, - renamed: Option, - parent_id: Option, + mut renamed: Option, + import_id: Option, ) { if self.is_importable_from_parent // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export` @@ -392,11 +412,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ => false, } { - self.modules - .last_mut() - .unwrap() - .items - .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id)); + if renamed == item.kind.ident().map(|ident| ident.name) { + renamed = None; + } + let key = (item.owner_id.def_id, renamed); + if let Some(import_id) = import_id { + self.modules + .last_mut() + .unwrap() + .items + .entry(key) + .and_modify(|v| v.2.push(import_id)) + .or_insert_with(|| (item, renamed, vec![import_id])); + } else { + self.modules.last_mut().unwrap().items.insert(key, (item, renamed, Vec::new())); + } } } @@ -468,7 +498,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ => false, }); let ident = match kind { - hir::UseKind::Single(ident) => Some(renamed.unwrap_or(ident.name)), + hir::UseKind::Single(ident) => Some(ident.name), hir::UseKind::Glob => None, hir::UseKind::ListStem => unreachable!(), }; diff --git a/tests/assembly/emit-intel-att-syntax.rs b/tests/assembly/emit-intel-att-syntax.rs new file mode 100644 index 0000000000000..7b479a0f79efd --- /dev/null +++ b/tests/assembly/emit-intel-att-syntax.rs @@ -0,0 +1,75 @@ +//@ assembly-output: emit-asm +//@ revisions: att intel +//@ [att] compile-flags: -Cllvm-args=-x86-asm-syntax=att +//@ [intel] compile-flags: -Cllvm-args=-x86-asm-syntax=intel +//@ only-x86_64 + +#![crate_type = "lib"] + +// CHECK-LABEL: naked_att: +// intel-CHECK: mov rax, qword ptr [rdi] +// intel-CHECK: ret +// att-CHECK: movq (%rdi), %rax +// att-CHECK: retq + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "sysv64" fn naked_att() { + std::arch::naked_asm!( + " + movq (%rdi), %rax + retq + ", + options(att_syntax), + ); +} + +// CHECK-LABEL: naked_intel: +// intel-CHECK: mov rax, rdi +// intel-CHECK: ret +// att-CHECK: movq (%rdi), %rax +// att-CHECK: retq + +#[unsafe(naked)] +#[unsafe(no_mangle)] +extern "sysv64" fn naked_intel() { + std::arch::naked_asm!( + " + mov rax, rdi + ret + ", + options(), + ); +} + +// CHECK-LABEL: global_att: +// intel-CHECK: mov rax, rdi +// intel-CHECK: ret +// att-CHECK: movq (%rdi), %rax +// att-CHECK: retq + +core::arch::global_asm!( + " + .globl global_att + global_att: + movq (%rdi), %rax + retq + ", + options(att_syntax), +); + +// CHECK-LABEL: global_intel: +// intel-CHECK: mov rax, rdi +// intel-CHECK: ret +// att-CHECK: movq (%rdi), %rax +// att-CHECK: retq + +core::arch::global_asm!( + " + .globl global_intel + global_intel: + mov rax, rdi + ret + ", + options(), +); diff --git a/tests/rustdoc-json/visibility/doc_hidden_default.rs b/tests/rustdoc-json/visibility/doc_hidden_default.rs new file mode 100644 index 0000000000000..3fa91b3c4ad2d --- /dev/null +++ b/tests/rustdoc-json/visibility/doc_hidden_default.rs @@ -0,0 +1,19 @@ +#![no_std] + +// Without `--document-hidden-items`, +// none of these items are present in rustdoc JSON. + +//@ !has "$.index[?(@.name=='func')]" +#[doc(hidden)] +pub fn func() {} + +//@ !has "$.index[?(@.name=='Unit')]" +#[doc(hidden)] +pub struct Unit; + +//@ !has "$.index[?(@.name=='hidden')]" +#[doc(hidden)] +pub mod hidden { + //@ !has "$.index[?(@.name=='Inner')]" + pub struct Inner; +} diff --git a/tests/rustdoc-json/visibility/doc_hidden_documented.rs b/tests/rustdoc-json/visibility/doc_hidden_documented.rs new file mode 100644 index 0000000000000..6e9ef48680bee --- /dev/null +++ b/tests/rustdoc-json/visibility/doc_hidden_documented.rs @@ -0,0 +1,17 @@ +//@ compile-flags: --document-hidden-items +#![no_std] + +//@ is "$.index[?(@.name=='func')].attrs" '["#[doc(hidden)]"]' +#[doc(hidden)] +pub fn func() {} + +//@ is "$.index[?(@.name=='Unit')].attrs" '["#[doc(hidden)]"]' +#[doc(hidden)] +pub struct Unit; + +//@ is "$.index[?(@.name=='hidden')].attrs" '["#[doc(hidden)]"]' +#[doc(hidden)] +pub mod hidden { + //@ is "$.index[?(@.name=='Inner')].attrs" '[]' + pub struct Inner; +} diff --git a/tests/rustdoc/reexport/merge-glob-and-non-glob.rs b/tests/rustdoc/reexport/merge-glob-and-non-glob.rs new file mode 100644 index 0000000000000..ff67859cb39af --- /dev/null +++ b/tests/rustdoc/reexport/merge-glob-and-non-glob.rs @@ -0,0 +1,41 @@ +// This test ensures that if an item is inlined from two different `use`, +// then it will use attributes from both of them. +// This is a regression test for . + +#![feature(no_core)] +#![no_core] +#![no_std] +#![crate_name = "foo"] + +// First we ensure we only have two items. +//@ has 'foo/index.html' +//@ count - '//dl[@class="item-table"]/dt' 2 +// We should also only have one section (Structs). +//@ count - '//h2[@class="section-header"]' 1 +// We now check the short docs. +//@ has - '//dl[@class="item-table"]/dd' 'Foobar Blob' +//@ has - '//dl[@class="item-table"]/dd' 'Tarte Tatin' + +//@ has 'foo/struct.Foo.html' +//@ has - '//*[@class="docblock"]' 'Foobar Blob' + +//@ has 'foo/struct.Another.html' +//@ has - '//*[@class="docblock"]' 'Tarte Tatin' + +mod raw { + /// Blob + pub struct Foo; + + /// Tatin + pub struct Another; +} + +/// Foobar +pub use raw::Foo; + +// Glob reexport attributes are ignored. +/// Baz +pub use raw::*; + +/// Tarte +pub use raw::Another as Another; diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 445dd75f8249b..bbe0714801c45 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,151 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls` LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:14:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:14:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:14:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:21:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:21:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:21:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:28:8 - | -LL | T: [const] FnOnce<()>, - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:28:8 - | -LL | T: [const] FnOnce<()>, - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:28:8 - | -LL | T: [const] FnOnce<()>, - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:35:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:35:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:35:8 - | -LL | T: [const] Fn<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:49:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:49:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/fn_trait_refs.rs:49:8 - | -LL | T: [const] FnMut<()> + [const] Destruct, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0277]: the trait bound `(i32, i32, i32): const PartialEq` is not satisfied --> $DIR/fn_trait_refs.rs:71:17 | @@ -161,31 +16,7 @@ error[E0277]: the trait bound `(i32, i32): const PartialEq` is not satisfied LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:16:5 - | -LL | f() - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:23:5 - | -LL | f() - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/fn_trait_refs.rs:30:5 - | -LL | f() - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 21 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0015, E0277, E0635. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0635. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 95e48b7b7c803..16db7791cd849 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,30 +1,3 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/unstable-const-fn-in-libcore.rs:19:32 - | -LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/unstable-const-fn-in-libcore.rs:19:32 - | -LL | const fn unwrap_or_else T>(self, f: F) -> T { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/unstable-const-fn-in-libcore.rs:24:26 - | -LL | Opt::None => f(), - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:61 | @@ -43,7 +16,6 @@ LL | const fn unwrap_or_else T>(self, f: F) -> T { LL | } | - value is dropped here -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index e17737d1860a1..051eb62d9cb81 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,22 +1,3 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:35 - | -LL | const fn with_positive [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:35 - | -LL | const fn with_positive [const] Fn(&'a Alias<'a>) + [const] Destruct>(fun: F) { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: unconstrained opaque type --> $DIR/normalize-tait-in-const.rs:14:26 | @@ -44,15 +25,6 @@ note: this item must have a `#[define_opaque(foo::Alias)]` attribute to be able LL | pub const fn filter_positive<'a>() -> &'a Alias<'a> { | ^^^^^^^^^^^^^^^ -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/normalize-tait-in-const.rs:28:5 - | -LL | fun(filter_positive()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0308. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs index 3365d57af7ce4..f407125129921 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.rs +++ b/tests/ui/intrinsics/const-eval-select-bad.rs @@ -5,13 +5,10 @@ use std::intrinsics::const_eval_select; const fn not_fn_items() { const_eval_select((), || {}, || {}); - //~^ ERROR this argument must be a function item - //~| ERROR this argument must be a function item + //~^ ERROR const FnOnce()` is not satisfied const_eval_select((), 42, 0xDEADBEEF); //~^ ERROR expected a `FnOnce()` closure //~| ERROR expected a `FnOnce()` closure - //~| ERROR this argument must be a function item - //~| ERROR this argument must be a function item } const fn foo(n: i32) -> i32 { @@ -40,7 +37,7 @@ const fn args_ty_mismatch() { const fn non_const_fn() { const_eval_select((1,), bar, bar); - //~^ ERROR this argument must be a `const fn` + //~^ ERROR the trait bound `fn(i32) -> bool {bar}: const FnOnce(i32)` is not satisfied } fn main() {} diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index bb159bed28224..d701f5ea90973 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -1,23 +1,16 @@ -error: this argument must be a function item +error[E0277]: the trait bound `{closure@$DIR/const-eval-select-bad.rs:7:27: 7:29}: const FnOnce()` is not satisfied --> $DIR/const-eval-select-bad.rs:7:27 | LL | const_eval_select((), || {}, || {}); - | ^^^^^ - | - = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:27: 7:29} - = help: consult the documentation on `const_eval_select` for more information - -error: this argument must be a function item - --> $DIR/const-eval-select-bad.rs:7:34 - | -LL | const_eval_select((), || {}, || {}); - | ^^^^^ + | ----------------- ^^^^^ + | | + | required by a bound introduced by this call | - = note: expected a function item, found {closure@$DIR/const-eval-select-bad.rs:7:34: 7:36} - = help: consult the documentation on `const_eval_select` for more information +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error[E0277]: expected a `FnOnce()` closure, found `{integer}` - --> $DIR/const-eval-select-bad.rs:10:27 + --> $DIR/const-eval-select-bad.rs:9:27 | LL | const_eval_select((), 42, 0xDEADBEEF); | ----------------- ^^ expected an `FnOnce()` closure, found `{integer}` @@ -30,7 +23,7 @@ note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error[E0277]: expected a `FnOnce()` closure, found `{integer}` - --> $DIR/const-eval-select-bad.rs:10:31 + --> $DIR/const-eval-select-bad.rs:9:31 | LL | const_eval_select((), 42, 0xDEADBEEF); | ----------------- ^^^^^^^^^^ expected an `FnOnce()` closure, found `{integer}` @@ -42,26 +35,8 @@ LL | const_eval_select((), 42, 0xDEADBEEF); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL -error: this argument must be a function item - --> $DIR/const-eval-select-bad.rs:10:27 - | -LL | const_eval_select((), 42, 0xDEADBEEF); - | ^^ - | - = note: expected a function item, found {integer} - = help: consult the documentation on `const_eval_select` for more information - -error: this argument must be a function item - --> $DIR/const-eval-select-bad.rs:10:31 - | -LL | const_eval_select((), 42, 0xDEADBEEF); - | ^^^^^^^^^^ - | - = note: expected a function item, found {integer} - = help: consult the documentation on `const_eval_select` for more information - error[E0271]: expected `bar` to return `i32`, but it returns `bool` - --> $DIR/const-eval-select-bad.rs:32:34 + --> $DIR/const-eval-select-bad.rs:29:34 | LL | const_eval_select((1,), foo, bar); | ----------------- ^^^ expected `i32`, found `bool` @@ -72,7 +47,7 @@ note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL error[E0631]: type mismatch in function arguments - --> $DIR/const-eval-select-bad.rs:37:32 + --> $DIR/const-eval-select-bad.rs:34:32 | LL | const fn foo(n: i32) -> i32 { | --------------------------- found signature defined here @@ -91,15 +66,18 @@ help: consider wrapping the function in a closure LL | const_eval_select((true,), |arg0: bool| foo(/* i32 */), baz); | ++++++++++++ +++++++++++ -error: this argument must be a `const fn` - --> $DIR/const-eval-select-bad.rs:42:29 +error[E0277]: the trait bound `fn(i32) -> bool {bar}: const FnOnce(i32)` is not satisfied + --> $DIR/const-eval-select-bad.rs:39:29 | LL | const_eval_select((1,), bar, bar); - | ^^^ + | ----------------- ^^^ + | | + | required by a bound introduced by this call | - = help: consult the documentation on `const_eval_select` for more information +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0271, E0277, E0631. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/linking/export-executable-symbols.rs b/tests/ui/linking/export-executable-symbols.rs new file mode 100644 index 0000000000000..aea5527b6a1c1 --- /dev/null +++ b/tests/ui/linking/export-executable-symbols.rs @@ -0,0 +1,30 @@ +//@ run-pass +//@ only-linux +//@ only-gnu +//@ compile-flags: -Zexport-executable-symbols +//@ edition: 2024 + +// Regression test for . + +#![feature(rustc_private)] + +extern crate libc; + +#[unsafe(no_mangle)] +fn hack() -> u64 { + 998244353 +} + +fn main() { + unsafe { + let handle = libc::dlopen(std::ptr::null(), libc::RTLD_NOW); + let ptr = libc::dlsym(handle, c"hack".as_ptr()); + let ptr: Option u64> = std::mem::transmute(ptr); + if let Some(f) = ptr { + assert!(f() == 998244353); + println!("symbol `hack` is found successfully"); + } else { + panic!("symbol `hack` is not found"); + } + } +} diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index b985e3da34511..b1080fe78bb5f 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -5,7 +5,7 @@ pub const _: () = { assert!((const || true)()); - //~^ ERROR cannot call non-const closure in constants + //~^ ERROR }: [const] Fn()` is not satisfied }; fn main() {} diff --git a/tests/ui/traits/const-traits/call.stderr b/tests/ui/traits/const-traits/call.stderr index e9bf64092f3b7..8e32cab6dfcfb 100644 --- a/tests/ui/traits/const-traits/call.stderr +++ b/tests/ui/traits/const-traits/call.stderr @@ -1,12 +1,9 @@ -error[E0015]: cannot call non-const closure in constants +error[E0277]: the trait bound `{closure@$DIR/call.rs:7:14: 7:22}: [const] Fn()` is not satisfied --> $DIR/call.rs:7:13 | LL | assert!((const || true)()); | ^^^^^^^^^^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constants - = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr index fdfe3b95d555a..1d8d5ff1b4f2e 100644 --- a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr +++ b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr @@ -1,31 +1,9 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-parse-not-item.rs:7:25 +error[E0277]: the trait bound `{closure@$DIR/const-closure-parse-not-item.rs:8:5: 8:18}: [const] Fn()` is not satisfied + --> $DIR/const-closure-parse-not-item.rs:7:20 | LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-parse-not-item.rs:7:25 - | -LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-parse-not-item.rs:7:25 - | -LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr index 89b202b34381b..fddd8d10bccc4 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -1,30 +1,9 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-trait-method-fail.rs:14:32 +error[E0277]: the trait bound `(): const Tr` is not satisfied + --> $DIR/const-closure-trait-method-fail.rs:18:23 | -LL | const fn need_const_closure i32>(x: T) -> i32 { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-trait-method-fail.rs:14:32 - | -LL | const fn need_const_closure i32>(x: T) -> i32 { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closure-trait-method-fail.rs:15:5 - | -LL | x(()) - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.rs b/tests/ui/traits/const-traits/const-closure-trait-method.rs index 831d6e27946d1..6477aa63c680b 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.rs +++ b/tests/ui/traits/const-traits/const-closure-trait-method.rs @@ -1,5 +1,6 @@ -//@ known-bug: #110395 -// FIXME check-pass +//@ check-pass +//@ revisions: next old +//@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr deleted file mode 100644 index 6de25dc11ef51..0000000000000 --- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-trait-method.rs:14:32 - | -LL | const fn need_const_closure i32>(x: T) -> i32 { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closure-trait-method.rs:14:32 - | -LL | const fn need_const_closure i32>(x: T) -> i32 { - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closure-trait-method.rs:15:5 - | -LL | x(()) - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-closures.rs b/tests/ui/traits/const-traits/const-closures.rs index 2f6f4dc4ba335..8f1c018ca5dd4 100644 --- a/tests/ui/traits/const-traits/const-closures.rs +++ b/tests/ui/traits/const-traits/const-closures.rs @@ -1,5 +1,6 @@ -//@ known-bug: #110395 -// FIXME check-pass +//@ check-pass +//@ revisions: next old +//@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr deleted file mode 100644 index 19869b470852d..0000000000000 --- a/tests/ui/traits/const-traits/const-closures.stderr +++ /dev/null @@ -1,103 +0,0 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:8:12 - | -LL | F: [const] FnOnce() -> u8, - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:9:12 - | -LL | F: [const] FnMut() -> u8, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:10:12 - | -LL | F: [const] Fn() -> u8, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:8:12 - | -LL | F: [const] FnOnce() -> u8, - | ^^^^^^^ can't be applied to `FnOnce` - | -note: `FnOnce` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:9:12 - | -LL | F: [const] FnMut() -> u8, - | ^^^^^^^ can't be applied to `FnMut` - | -note: `FnMut` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:10:12 - | -LL | F: [const] Fn() -> u8, - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:23:20 - | -LL | const fn answer u8>(f: &F) -> u8 { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-closures.rs:23:20 - | -LL | const fn answer u8>(f: &F) -> u8 { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:24:5 - | -LL | f() + f() - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:24:11 - | -LL | f() + f() - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/const-closures.rs:12:5 - | -LL | f() * 7 - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 11 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs index 92427039b4333..30002038f6891 100644 --- a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs +++ b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.rs @@ -1,3 +1,4 @@ +//@ known-bug: #110395 //@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl)] #![allow(incomplete_features)] @@ -11,7 +12,7 @@ impl Foo for () { } fn main() { - (const || { (()).foo() })(); - //~^ ERROR: cannot call non-const method `<() as Foo>::foo` in constant functions + (const || (()).foo())(); + // ^ ERROR: cannot call non-const method `<() as Foo>::foo` in constant functions // FIXME(const_trait_impl) this should probably say constant closures } diff --git a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr index c08642ba5a31c..dab3f14161fac 100644 --- a/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr +++ b/tests/ui/traits/const-traits/const_closure-const_trait_impl-ice-113381.stderr @@ -1,11 +1,9 @@ -error[E0015]: cannot call non-const method `<() as Foo>::foo` in constant functions - --> $DIR/const_closure-const_trait_impl-ice-113381.rs:14:22 +error[E0277]: the trait bound `{closure@$DIR/const_closure-const_trait_impl-ice-113381.rs:15:6: 15:14}: [const] Fn()` is not satisfied + --> $DIR/const_closure-const_trait_impl-ice-113381.rs:15:5 | -LL | (const || { (()).foo() })(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | (const || (()).foo())(); + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs index 026f2c0d60326..8ee3db445d072 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs @@ -1,16 +1,14 @@ #![feature(const_trait_impl)] const fn test() -> impl [const] Fn() { - //~^ ERROR `[const]` can only be applied to `#[const_trait]` traits - //~| ERROR `[const]` can only be applied to `#[const_trait]` traits - //~| ERROR `[const]` can only be applied to `#[const_trait]` traits + //~^ ERROR: }: [const] Fn()` is not satisfied const move || { //~ ERROR const closures are experimental let sl: &[u8] = b"foo"; match sl { [first, remainder @ ..] => { assert_eq!(first, &b'f'); - //~^ ERROR cannot call non-const function + // FIXME(const_closures) ^ ERROR cannot call non-const function } [] => panic!(), } diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr index 78d7b962cc42f..abbe0a0070aa2 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr @@ -1,5 +1,5 @@ error[E0658]: const closures are experimental - --> $DIR/ice-112822-expected-type-for-param.rs:7:5 + --> $DIR/ice-112822-expected-type-for-param.rs:5:5 | LL | const move || { | ^^^^^ @@ -8,45 +8,13 @@ LL | const move || { = help: add `#![feature(const_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/ice-112822-expected-type-for-param.rs:3:25 +error[E0277]: the trait bound `{closure@$DIR/ice-112822-expected-type-for-param.rs:5:5: 5:18}: [const] Fn()` is not satisfied + --> $DIR/ice-112822-expected-type-for-param.rs:3:20 | LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/ice-112822-expected-type-for-param.rs:3:25 - | -LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/ice-112822-expected-type-for-param.rs:3:25 - | -LL | const fn test() -> impl [const] Fn() { - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const function `core::panicking::assert_failed::<&u8, &u8>` in constant functions - --> $DIR/ice-112822-expected-type-for-param.rs:12:17 - | -LL | assert_eq!(first, &b'f'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs deleted file mode 100644 index f1dbd94716171..0000000000000 --- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(incomplete_features)] -#![feature(generic_const_exprs, const_trait_impl)] - -const fn with_positive() {} -//~^ ERROR `[const]` can only be applied to `#[const_trait]` traits -//~| ERROR `[const]` can only be applied to `#[const_trait]` traits - -pub fn main() {} diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr deleted file mode 100644 index 1eccb16b46e7d..0000000000000 --- a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/ice-123664-unexpected-bound-var.rs:4:27 - | -LL | const fn with_positive() {} - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/ice-123664-unexpected-bound-var.rs:4:27 - | -LL | const fn with_positive() {} - | ^^^^^^^ can't be applied to `Fn` - | -note: `Fn` can't be used with `[const]` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs index fa0f786964488..d0470fa345848 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs @@ -11,5 +11,5 @@ impl Foo for () { fn main() { (const || { (()).foo() })(); - //~^ ERROR: cannot call non-const method + //~^ ERROR: }: [const] Fn()` is not satisfied } diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr index 2d33406c22240..dcf65ab694080 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -1,11 +1,9 @@ -error[E0015]: cannot call non-const method `<() as Foo>::foo` in constant functions - --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22 +error[E0277]: the trait bound `{closure@$DIR/non-const-op-const-closure-non-const-outer.rs:13:6: 13:14}: [const] Fn()` is not satisfied + --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:5 | LL | (const || { (()).foo() })(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`.