diff options
442 files changed, 6506 insertions, 4384 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 84933540147..260c9fe44ba 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -21,7 +21,6 @@ #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(maybe_uninit_slice)] -#![feature(new_uninit)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(strict_provenance)] diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 43d87b96ead..f1dddb3acac 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -486,6 +486,9 @@ impl Token { } /// Returns `true` if the token can appear at the start of an expression. + /// + /// **NB**: Take care when modifying this function, since it will change + /// the stable set of tokens that are allowed to match an expr nonterminal. pub fn can_begin_expr(&self) -> bool { match self.uninterpolate().kind { Ident(name, is_raw) => @@ -504,10 +507,13 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => matches!(&**nt, NtLiteral(..) | - NtExpr(..) | - NtBlock(..) | - NtPath(..)), + Interpolated(ref nt) => + matches!(&**nt, + NtBlock(..) | + NtExpr(..) | + NtLiteral(..) | + NtPath(..) + ), _ => false, } } @@ -515,23 +521,32 @@ impl Token { /// Returns `true` if the token can appear at the start of a pattern. /// /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now. - pub fn can_begin_pattern(&self) -> bool { - match self.uninterpolate().kind { - Ident(name, is_raw) => - ident_can_begin_expr(name, self.span, is_raw), // value name or keyword - | OpenDelim(Delimiter::Bracket | Delimiter::Parenthesis) // tuple or array - | Literal(..) // literal - | BinOp(Minus) // unary minus - | BinOp(And) // reference - | AndAnd // double reference - // DotDotDot is no longer supported - | DotDot | DotDotDot | DotDotEq // ranges - | Lt | BinOp(Shl) // associated path - | PathSep => true, // global path - Interpolated(ref nt) => matches!(&**nt, NtLiteral(..) | - NtPat(..) | - NtBlock(..) | - NtPath(..)), + pub fn can_begin_pattern(&self, pat_kind: NtPatKind) -> bool { + match &self.uninterpolate().kind { + // box, ref, mut, and other identifiers (can stricten) + Ident(..) | NtIdent(..) | + OpenDelim(Delimiter::Parenthesis) | // tuple pattern + OpenDelim(Delimiter::Bracket) | // slice pattern + BinOp(And) | // reference + BinOp(Minus) | // negative literal + AndAnd | // double reference + Literal(_) | // literal + DotDot | // range pattern (future compat) + DotDotDot | // range pattern (future compat) + PathSep | // path + Lt | // path (UFCS constant) + BinOp(Shl) => true, // path (double UFCS) + // leading vert `|` or-pattern + BinOp(Or) => matches!(pat_kind, PatWithOr), + Interpolated(nt) => + matches!(&**nt, + | NtExpr(..) + | NtLiteral(..) + | NtMeta(..) + | NtPat(..) + | NtPath(..) + | NtTy(..) + ), _ => false, } } diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index bf40c9b66c6..8c742d2aaf4 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -4,9 +4,10 @@ use std::borrow::Cow; use rustc_ast::visit::Visitor; use rustc_ast::*; use rustc_data_structures::fx::FxIndexMap; +use rustc_hir as hir; +use rustc_session::config::FmtDebug; use rustc_span::symbol::{kw, Ident}; use rustc_span::{sym, Span, Symbol}; -use {rustc_ast as ast, rustc_hir as hir}; use super::LoweringContext; @@ -243,7 +244,10 @@ fn make_argument<'hir>( hir::LangItem::FormatArgument, match ty { Format(Display) => sym::new_display, - Format(Debug) => sym::new_debug, + Format(Debug) => match ctx.tcx.sess.opts.unstable_opts.fmt_debug { + FmtDebug::Full | FmtDebug::Shallow => sym::new_debug, + FmtDebug::None => sym::new_debug_noop, + }, Format(LowerExp) => sym::new_lower_exp, Format(UpperExp) => sym::new_upper_exp, Format(Octal) => sym::new_octal, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 755e6ee0d3e..57d9c076150 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -1,5 +1,6 @@ use rustc_ast::{self as ast, EnumDef, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_session::config::FmtDebug; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; @@ -49,6 +50,11 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> // We want to make sure we have the ctxt set so that we can use unstable methods let span = cx.with_def_site_ctxt(span); + let fmt_detail = cx.sess.opts.unstable_opts.fmt_debug; + if fmt_detail == FmtDebug::None { + return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new()))); + } + let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (substr.type_ident, *vdata, fields), EnumMatching(_, v, fields) => (v.ident, &v.data, fields), @@ -61,6 +67,13 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> let name = cx.expr_str(span, ident.name); let fmt = substr.nonselflike_args[0].clone(); + // Fieldless enums have been special-cased earlier + if fmt_detail == FmtDebug::Shallow { + let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); + let expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]); + return BlockOrExpr::new_expr(expr); + } + // Struct and tuples are similar enough that we use the same code for both, // with some extra pieces for structs due to the field names. let (is_struct, args_per_field) = match vdata { diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index c88c5bd35a5..bc41d33a609 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -11,7 +11,6 @@ use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; -use smallvec::{smallvec, SmallVec}; use thin_vec::{thin_vec, ThinVec}; macro_rules! path { @@ -68,43 +67,63 @@ pub(crate) fn expand_deriving_smart_ptr( }; // Convert generic parameters (from the struct) into generic args. - let mut pointee_param = None; - let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![]; - let self_params = generics + let self_params: Vec<_> = generics .params .iter() - .enumerate() - .map(|(idx, p)| match p.kind { + .map(|p| match p.kind { GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)), - GenericParamKind::Type { .. } => { - if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) { - if pointee_param.is_some() { - multiple_pointee_diag.push(cx.dcx().struct_span_err( - p.span(), - "`SmartPointer` can only admit one type as pointee", - )); - } else { - pointee_param = Some(idx); - } - } - GenericArg::Type(cx.ty_ident(p.span(), p.ident)) - } + GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(p.span(), p.ident)), GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)), }) - .collect::<Vec<_>>(); - let Some(pointee_param_idx) = pointee_param else { + .collect(); + let type_params: Vec<_> = generics + .params + .iter() + .enumerate() + .filter_map(|(idx, p)| { + if let GenericParamKind::Type { .. } = p.kind { + Some((idx, p.span(), p.attrs().iter().any(|attr| attr.has_name(sym::pointee)))) + } else { + None + } + }) + .collect(); + + let pointee_param_idx = if type_params.is_empty() { + // `#[derive(SmartPointer)]` requires at least one generic type on the target `struct` cx.dcx().struct_span_err( span, - "At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits", + "`SmartPointer` can only be derived on `struct`s that are generic over at least one type", ).emit(); return; - }; - if !multiple_pointee_diag.is_empty() { - for diag in multiple_pointee_diag { - diag.emit(); + } else if type_params.len() == 1 { + // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such + type_params[0].0 + } else { + let mut pointees = type_params + .iter() + .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) + .fuse(); + match (pointees.next(), pointees.next()) { + (Some((idx, _span)), None) => idx, + (None, _) => { + cx.dcx().struct_span_err( + span, + "exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits", + ).emit(); + return; + } + (Some((_, one)), Some((_, another))) => { + cx.dcx() + .struct_span_err( + vec![one, another], + "only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits", + ) + .emit(); + return; + } } - return; - } + }; // Create the type of `self`. let path = cx.path_all(span, false, vec![name_ident], self_params.clone()); diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 317e970d704..92a857c2adc 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -521,13 +521,20 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let function_features = function_features .iter() - .flat_map(|feat| { - llvm_util::to_llvm_features(cx.tcx.sess, feat).into_iter().map(|f| format!("+{f}")) - }) + // Convert to LLVMFeatures and filter out unavailable ones + .flat_map(|feat| llvm_util::to_llvm_features(cx.tcx.sess, feat)) + // Convert LLVMFeatures & dependencies to +<feats>s + .flat_map(|feat| feat.into_iter().map(|f| format!("+{f}"))) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) + // HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled + // It only exists as a feature in LLVM 18, cannot be passed down for any other version + .chain(match &*cx.tcx.sess.target.arch { + "aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()], + _ => vec![], + }) .collect::<Vec<String>>(); if cx.tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index adf7e933f43..a5c27d2282e 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -571,6 +571,7 @@ pub(crate) unsafe fn llvm_optimize( cgcx.opts.cg.linker_plugin_lto.enabled(), config.no_prepopulate_passes, config.verify_llvm_ir, + config.lint_llvm_ir, using_thin_buffers, config.merge_functions, unroll_loops, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index cabdd310d1f..d7a4f105f3c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::coverage::{ - CodeRegion, ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, + ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion, }; /// Must match the layout of `LLVMRustCounterKind`. @@ -236,9 +236,10 @@ impl CounterMappingRegion { pub(crate) fn from_mapping( mapping_kind: &MappingKind, local_file_id: u32, - code_region: &CodeRegion, + source_region: &SourceRegion, ) -> Self { - let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = + source_region; match *mapping_kind { MappingKind::Code(term) => Self::code_region( Counter::from_term(term), diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 44eafab6060..5ed640b840e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -2,8 +2,8 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ - CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, - MappingKind, Op, + CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, + SourceRegion, }; use rustc_middle::ty::Instance; use rustc_span::Symbol; @@ -201,7 +201,7 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Returns an iterator over all filenames used by this function's mappings. pub(crate) fn all_file_names(&self) -> impl Iterator<Item = Symbol> + Captures<'_> { - self.function_coverage_info.mappings.iter().map(|mapping| mapping.code_region.file_name) + self.function_coverage_info.mappings.iter().map(|mapping| mapping.source_region.file_name) } /// Convert this function's coverage expression data into a form that can be @@ -230,12 +230,12 @@ impl<'tcx> FunctionCoverage<'tcx> { /// that will be used by `mapgen` when preparing for FFI. pub(crate) fn counter_regions( &self, - ) -> impl Iterator<Item = (MappingKind, &CodeRegion)> + ExactSizeIterator { + ) -> impl Iterator<Item = (MappingKind, &SourceRegion)> + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let Mapping { kind, code_region } = mapping; + let Mapping { kind, source_region } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, code_region) + (kind, source_region) }) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5e0d7418993..138cc3219aa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2225,6 +2225,7 @@ unsafe extern "C" { IsLinkerPluginLTO: bool, NoPrepopulatePasses: bool, VerifyIR: bool, + LintIR: bool, UseThinLTOBuffers: bool, MergeFunctions: bool, UnrollLoops: bool, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7af5eb9278f..618602ed70f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -209,7 +209,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { +pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFeature<'a>> { let arch = if sess.target.arch == "x86_64" { "x86" } else if sess.target.arch == "arm64ec" { @@ -218,40 +218,59 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a &*sess.target.arch }; match (arch, s) { - ("x86", "sse4.2") => { - LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) - } - ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"), - ("x86", "rdrand") => LLVMFeature::new("rdrnd"), - ("x86", "bmi1") => LLVMFeature::new("bmi"), - ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"), - ("x86", "lahfsahf") => LLVMFeature::new("sahf"), - ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"), - ("aarch64", "dpb") => LLVMFeature::new("ccpp"), - ("aarch64", "dpb2") => LLVMFeature::new("ccdp"), - ("aarch64", "frintts") => LLVMFeature::new("fptoint"), - ("aarch64", "fcma") => LLVMFeature::new("complxnum"), - ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"), - ("aarch64", "paca") => LLVMFeature::new("pauth"), - ("aarch64", "pacg") => LLVMFeature::new("pauth"), + ("x86", "sse4.2") => Some(LLVMFeature::with_dependency( + "sse4.2", + TargetFeatureFoldStrength::EnableOnly("crc32"), + )), + ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")), + ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")), + ("x86", "bmi1") => Some(LLVMFeature::new("bmi")), + ("x86", "cmpxchg16b") => Some(LLVMFeature::new("cx16")), + ("x86", "lahfsahf") => Some(LLVMFeature::new("sahf")), + ("aarch64", "rcpc2") => Some(LLVMFeature::new("rcpc-immo")), + ("aarch64", "dpb") => Some(LLVMFeature::new("ccpp")), + ("aarch64", "dpb2") => Some(LLVMFeature::new("ccdp")), + ("aarch64", "frintts") => Some(LLVMFeature::new("fptoint")), + ("aarch64", "fcma") => Some(LLVMFeature::new("complxnum")), + ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")), + ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), + ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), + ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { - LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")) + Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))) } // In LLVM neon implicitly enables fp, but we manually enable // neon when a feature only implicitly enables fp - ("aarch64", "fhm") => LLVMFeature::new("fp16fml"), - ("aarch64", "fp16") => LLVMFeature::new("fullfp16"), + ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")), + ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), + // Filter out features that are not supported by the current LLVM version + ("aarch64", "faminmax") if get_version().0 < 18 => None, + ("aarch64", "fp8") if get_version().0 < 18 => None, + ("aarch64", "fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "fp8fma") if get_version().0 < 18 => None, + ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("aarch64", "lut") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f16") if get_version().0 < 18 => None, + ("aarch64", "sme-f8f32") if get_version().0 < 18 => None, + ("aarch64", "sme-fa64") if get_version().0 < 18 => None, + ("aarch64", "sme-lutv2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot2") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8dot4") if get_version().0 < 18 => None, + ("aarch64", "ssve-fp8fma") if get_version().0 < 18 => None, + ("aarch64", "v9.5a") if get_version().0 < 18 => None, // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called // `fast-unaligned-access`. In LLVM 19, it was split back out. ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { - LLVMFeature::new("fast-unaligned-access") + Some(LLVMFeature::new("fast-unaligned-access")) } // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled. ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => { - LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")) + Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512"))) } - (_, s) => LLVMFeature::new(s), + (_, s) => Some(LLVMFeature::new(s)), } } @@ -291,13 +310,17 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { return true; } // check that all features in a given smallvec are enabled - for llvm_feature in to_llvm_features(sess, feature) { - let cstr = SmallCStr::new(llvm_feature); - if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { - return false; + if let Some(feat) = to_llvm_features(sess, feature) { + for llvm_feature in feat { + let cstr = SmallCStr::new(llvm_feature); + if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } { + return false; + } } + true + } else { + false } - true }) .map(|(feature, _, _)| Symbol::intern(feature)), ); @@ -386,9 +409,9 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach .target .supported_target_features() .iter() - .map(|(feature, _gate, _implied)| { + .filter_map(|(feature, _gate, _implied)| { // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name; + let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name; let desc = match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() { Some(index) => { @@ -398,7 +421,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach None => "", }; - (*feature, desc) + Some((*feature, desc)) }) .collect::<Vec<_>>(); @@ -595,7 +618,7 @@ pub(crate) fn global_llvm_features( if feature_state.is_none() { let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| { - let llvm_features = to_llvm_features(sess, rust_feature); + let llvm_features = to_llvm_features(sess, rust_feature)?; if llvm_features.contains(feature) && !llvm_features.contains(rust_feature) { @@ -641,7 +664,7 @@ pub(crate) fn global_llvm_features( // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - let llvm_feature = to_llvm_features(sess, feature); + let llvm_feature = to_llvm_features(sess, feature)?; Some( std::iter::once(format!( @@ -691,6 +714,9 @@ fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { let feature = s .strip_prefix(&['+', '-'][..]) .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); + if s.is_empty() { + return None; + } // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4d19425255f..e8143b9a5f3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2,7 +2,7 @@ use std::collections::BTreeSet; use std::ffi::OsString; use std::fs::{read, File, OpenOptions}; use std::io::{BufWriter, Write}; -use std::ops::Deref; +use std::ops::{ControlFlow, Deref}; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; @@ -18,8 +18,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; +use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs}; use rustc_middle::bug; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; @@ -2110,50 +2110,19 @@ fn add_library_search_dirs( return; } - // Library search paths explicitly supplied by user (`-L` on the command line). - for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() { - cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); - } - for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() { - // Contrary to the `-L` docs only framework-specific paths are considered here. - if search_path.kind != PathKind::All { - cmd.framework_path(&search_path.dir); - } - } - - // The toolchain ships some native library components and self-contained linking was enabled. - // Add the self-contained library directory to search paths. - if self_contained_components.intersects( - LinkSelfContainedComponents::LIBC - | LinkSelfContainedComponents::UNWIND - | LinkSelfContainedComponents::MINGW, - ) { - let lib_path = sess.target_tlib_path.dir.join("self-contained"); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); - } - - // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot - // library directory instead of the self-contained directories. - // Sanitizer libraries have the same issue and are also linked by name on Apple targets. - // The targets here should be in sync with `copy_third_party_objects` in bootstrap. - // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind - // and sanitizers to self-contained directory, and stop adding this search path. - if sess.target.vendor == "fortanix" - || sess.target.os == "linux" - || sess.target.os == "fuchsia" - || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() - { - cmd.include_path(&fix_windows_verbatim_for_gcc(&sess.target_tlib_path.dir)); - } - - // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks - // we must have the support library stubs in the library search path (#121430). - if let Some(sdk_root) = apple_sdk_root - && sess.target.llvm_target.contains("macabi") - { - cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); - cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); - } + walk_native_lib_search_dirs( + sess, + self_contained_components, + apple_sdk_root, + |dir, is_framework| { + if is_framework { + cmd.framework_path(dir); + } else { + cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); + } + ControlFlow::<()>::Continue(()) + }, + ); } /// Add options making relocation sections in the produced ELF files read-only diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index fbab988a32b..cb266247e0d 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -7,7 +7,7 @@ use std::{env, iter, mem, str}; use cc::windows_registry; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_metadata::find_native_static_library; +use rustc_metadata::{find_native_static_library, try_find_native_static_library}; use rustc_middle::bug; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols; @@ -891,9 +891,15 @@ impl<'a> Linker for MsvcLinker<'a> { } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) { - let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let suffix = if verbatim { "" } else { ".lib" }; - self.link_arg(format!("{prefix}{name}{suffix}")); + // On MSVC-like targets rustc supports static libraries using alternative naming + // scheme (`libfoo.a`) unsupported by linker, search for such libraries manually. + if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) { + self.link_staticlib_by_path(&path, whole_archive); + } else { + let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; + let suffix = if verbatim { "" } else { ".lib" }; + self.link_arg(format!("{prefix}{name}{suffix}")); + } } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7ad31802454..feb27c148a1 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -112,6 +112,7 @@ pub struct ModuleConfig { // Miscellaneous flags. These are mostly copied from command-line // options. pub verify_llvm_ir: bool, + pub lint_llvm_ir: bool, pub no_prepopulate_passes: bool, pub no_builtins: bool, pub time_module: bool, @@ -237,6 +238,7 @@ impl ModuleConfig { bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(), verify_llvm_ir: sess.verify_llvm_ir(), + lint_llvm_ir: sess.opts.unstable_opts.lint_llvm_ir, no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, no_builtins: no_builtins || sess.target.no_builtins, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4ab20c154cc..209750d6ba6 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,5 +1,6 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; use rustc_hir as hir; @@ -8,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{lang_items, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -17,6 +18,7 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; +use rustc_target::abi::VariantIdx; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; @@ -78,6 +80,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; + let fn_sig_outer = || { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } + }; + for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -85,16 +94,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { - Some(tcx.fn_sig(did)) - } else { + let sig = fn_sig_outer(); + if sig.is_none() { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); - None } + sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -613,7 +618,93 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - // If a function uses #[target_feature] it can't be inlined into general + if let Some(sig) = fn_sig_outer() { + // Collect target features from types reachable from arguments. + // We define a type as "reachable" if: + // - it is a function argument + // - it is a field of a reachable struct + // - there is a reachable reference to it + // FIXME(struct_target_features): we may want to cache the result of this computation. + let mut visited_types = FxHashSet::default(); + let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); + let mut additional_tf = vec![]; + + while let Some(ty) = reachable_types.pop() { + if visited_types.contains(&ty) { + continue; + } + visited_types.insert(ty); + match ty.kind() { + ty::Alias(..) => { + if let Ok(t) = + tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) + { + reachable_types.push(t) + } + } + + ty::Ref(_, inner, _) => reachable_types.push(*inner), + ty::Tuple(tys) => reachable_types.extend(tys.iter()), + ty::Adt(adt_def, args) => { + additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); + // This only recurses into structs as i.e. an Option<TargetFeature> is an ADT + // that doesn't actually always contain a TargetFeature. + if adt_def.is_struct() { + reachable_types.extend( + adt_def + .variant(VariantIdx::from_usize(0)) + .fields + .iter() + .map(|field| field.ty(tcx, args)), + ); + } + } + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Foreign(..) + | ty::Str + | ty::Array(..) + | ty::Pat(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Infer(..) + | ty::Error(..) => (), + } + } + + // FIXME(struct_target_features): is this really necessary? + if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a function with non-Rust ABI", + ); + } + if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { + tcx.dcx().span_err( + tcx.hir().span(tcx.local_def_id_to_hir_id(did)), + "cannot use a struct with target features in a #[inline(always)] function", + ); + } + codegen_fn_attrs + .target_features + .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); + } + + // If a function uses non-default target_features it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. @@ -758,6 +849,20 @@ fn check_link_name_xor_ordinal( } } +fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { + let mut features = vec![]; + let supported_features = tcx.supported_target_features(LOCAL_CRATE); + for attr in tcx.get_attrs(def_id, sym::target_feature) { + from_target_feature(tcx, attr, supported_features, &mut features); + } + tcx.arena.alloc_slice(&features) +} + pub fn provide(providers: &mut Providers) { - *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; + *providers = Providers { + codegen_fn_attrs, + should_inherit_track_caller, + struct_target_features, + ..*providers + }; } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index d7d64180ec9..db788b6b151 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -402,9 +402,6 @@ const_eval_unallowed_mutable_refs = const_eval_unallowed_op_in_const_context = {$msg} -const_eval_unavailable_target_features_for_fn = - calling a function that requires unavailable target features: {$unavailable_feats} - const_eval_uninhabited_enum_variant_read = read discriminant of an uninhabited enum variant const_eval_uninhabited_enum_variant_written = diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index f99283c49f5..61e8007e10e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -311,34 +311,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(()) } - fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> { - // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988 - let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - if !self.tcx.sess.target.is_like_wasm - && attrs - .target_features - .iter() - .any(|feature| !self.tcx.sess.target_features.contains(&feature.name)) - { - throw_ub_custom!( - fluent::const_eval_unavailable_target_features_for_fn, - unavailable_feats = attrs - .target_features - .iter() - .filter(|&feature| !feature.implied - && !self.tcx.sess.target_features.contains(&feature.name)) - .fold(String::new(), |mut s, feature| { - if !s.is_empty() { - s.push_str(", "); - } - s.push_str(feature.name.as_str()); - s - }), - ); - } - Ok(()) - } - /// The main entry point for creating a new stack frame: performs ABI checks and initializes /// arguments. #[instrument(skip(self), level = "trace")] @@ -360,20 +332,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_unsup_format!("calling a c-variadic function is not supported"); } - if M::enforce_abi(self) { - if caller_fn_abi.conv != callee_fn_abi.conv { - throw_ub_custom!( - fluent::const_eval_incompatible_calling_conventions, - callee_conv = format!("{:?}", callee_fn_abi.conv), - caller_conv = format!("{:?}", caller_fn_abi.conv), - ) - } + if caller_fn_abi.conv != callee_fn_abi.conv { + throw_ub_custom!( + fluent::const_eval_incompatible_calling_conventions, + callee_conv = format!("{:?}", callee_fn_abi.conv), + caller_conv = format!("{:?}", caller_fn_abi.conv), + ) } // Check that all target features required by the callee (i.e., from // the attribute `#[target_feature(enable = ...)]`) are enabled at // compile time. - self.check_fn_target_features(instance)?; + M::check_fn_target_features(self, instance)?; if !callee_fn_abi.can_unwind { // The callee cannot unwind, so force the `Unreachable` unwind handling. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index aef39b9af2f..bedc56de0da 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -684,19 +684,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(layout.is_sized()); let get_bytes = |this: &InterpCx<'tcx, M>, - op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>, - size| + op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>| -> InterpResult<'tcx, &[u8]> { let ptr = this.read_pointer(op)?; - let Some(alloc_ref) = self.get_ptr_alloc(ptr, size)? else { + this.check_ptr_align(ptr, layout.align.abi)?; + let Some(alloc_ref) = self.get_ptr_alloc(ptr, layout.size)? else { // zero-sized access return Ok(&[]); }; alloc_ref.get_bytes_strip_provenance() }; - let lhs_bytes = get_bytes(self, lhs, layout.size)?; - let rhs_bytes = get_bytes(self, rhs, layout.size)?; + let lhs_bytes = get_bytes(self, lhs)?; + let rhs_bytes = get_bytes(self, rhs)?; Ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 761ab81e228..88453245b84 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -173,11 +173,6 @@ pub trait Machine<'tcx>: Sized { false } - /// Whether function calls should be [ABI](CallAbi)-checked. - fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool { - true - } - /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually /// check for overflow. fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool; @@ -238,6 +233,13 @@ pub trait Machine<'tcx>: Sized { unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>; + /// Check whether the given function may be executed on the current machine, in terms of the + /// target features is requires. + fn check_fn_target_features( + _ecx: &InterpCx<'tcx, Self>, + _instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx>; + /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'tcx, Self>, @@ -280,6 +282,9 @@ pub trait Machine<'tcx>: Sized { Ok(()) } + /// Determines the result of a `NullaryOp::UbChecks` invocation. + fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>; + /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction. /// You can use this to detect long or endlessly running programs. #[inline] @@ -615,6 +620,16 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] + fn check_fn_target_features( + _ecx: &InterpCx<$tcx, Self>, + _instance: ty::Instance<$tcx>, + ) -> InterpResult<$tcx> { + // For now we don't do any checking here. We can't use `tcx.sess` because that can differ + // between crates, and we need to ensure that const-eval always behaves the same. + Ok(()) + } + + #[inline(always)] fn call_extra_fn( _ecx: &mut InterpCx<$tcx, Self>, fn_val: !, @@ -628,6 +643,13 @@ pub macro compile_time_machine(<$tcx: lifetime>) { } #[inline(always)] + fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> { + // We can't look at `tcx.sess` here as that can differ across crates, which can lead to + // unsound differences in evaluating the same constant at different instantiation sites. + Ok(true) + } + + #[inline(always)] fn adjust_global_allocation<'b>( _ecx: &InterpCx<$tcx, Self>, _id: AllocId, diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 2f860f9f942..e9ba12dbcc4 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -512,7 +512,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } - UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx), + UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), }) } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 820ba96b100..e49ae60e890 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -393,13 +393,17 @@ fn run_compiler( let linker = compiler.enter(|queries| { let early_exit = || early_exit().map(|_| None); + + // Parse the crate root source code (doesn't parse submodules yet) + // Everything else is parsed during macro expansion. queries.parse()?; - if let Some(ppm) = &sess.opts.pretty { - if ppm.needs_ast_map() { + // If pretty printing is requested: Figure out the representation, print it and exit + if let Some(pp_mode) = sess.opts.pretty { + if pp_mode.needs_ast_map() { queries.global_ctxt()?.enter(|tcx| { tcx.ensure().early_lint_checks(()); - pretty::print(sess, *ppm, pretty::PrintExtra::NeedsAstMap { tcx }); + pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx }); Ok(()) })?; @@ -410,7 +414,7 @@ fn run_compiler( let krate = queries.parse()?; pretty::print( sess, - *ppm, + pp_mode, pretty::PrintExtra::AfterParsing { krate: &*krate.borrow() }, ); } @@ -465,12 +469,8 @@ fn run_compiler( linker.link(sess, codegen_backend)? } - if sess.opts.unstable_opts.print_fuel.is_some() { - eprintln!( - "Fuel used by {}: {}", - sess.opts.unstable_opts.print_fuel.as_ref().unwrap(), - sess.print_fuel.load(Ordering::SeqCst) - ); + if let Some(fuel) = sess.opts.unstable_opts.print_fuel.as_deref() { + eprintln!("Fuel used by {}: {}", fuel, sess.print_fuel.load(Ordering::SeqCst)); } Ok(()) @@ -487,36 +487,43 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileNa (odir, ofile) } -// Extract input (string or file and optional path) from matches. +/// Extract input (string or file and optional path) from matches. +/// This handles reading from stdin if `-` is provided. fn make_input( early_dcx: &EarlyDiagCtxt, free_matches: &[String], ) -> Result<Option<Input>, ErrorGuaranteed> { - let [ifile] = free_matches else { return Ok(None) }; - if ifile == "-" { - let mut src = String::new(); - if io::stdin().read_to_string(&mut src).is_err() { - // Immediately stop compilation if there was an issue reading - // the input (for example if the input stream is not UTF-8). - let reported = - early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); - return Err(reported); - } - if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + let [input_file] = free_matches else { return Ok(None) }; + + if input_file != "-" { + // Normal `Input::File` + return Ok(Some(Input::File(PathBuf::from(input_file)))); + } + + // read from stdin as `Input::Str` + let mut input = String::new(); + if io::stdin().read_to_string(&mut input).is_err() { + // Immediately stop compilation if there was an issue reading + // the input (for example if the input stream is not UTF-8). + let reported = + early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); + return Err(reported); + } + + let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") { + Ok(path) => { let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect( "when UNSTABLE_RUSTDOC_TEST_PATH is set \ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set", ); let line = isize::from_str_radix(&line, 10) .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number"); - let file_name = FileName::doc_test_source_code(PathBuf::from(path), line); - Ok(Some(Input::Str { name: file_name, input: src })) - } else { - Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src })) + FileName::doc_test_source_code(PathBuf::from(path), line) } - } else { - Ok(Some(Input::File(PathBuf::from(ifile)))) - } + Err(_) => FileName::anon_source_code(&input), + }; + + Ok(Some(Input::Str { name, input })) } /// Whether to stop or continue compilation. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 2747a14d60a..e2491922b8d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -37,6 +37,8 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)), (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)), (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)), + // this is consistent with naming of the compiler flag it's for + (sym::fmt_debug, sym::fmt_debug, cfg_fn!(fmt_debug)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4524458023d..7ea037ca8b2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -302,6 +302,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. + (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), @@ -470,6 +471,8 @@ declare_features! ( (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. (unstable, ffi_pure, "1.45.0", Some(58329)), + /// Controlling the behavior of fmt::Debug + (unstable, fmt_debug, "CURRENT_RUSTC_VERSION", Some(129709)), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. @@ -594,6 +597,8 @@ declare_features! ( (unstable, strict_provenance, "1.61.0", Some(95228)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows structs to carry target_feature information. + (incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)), /// Allows the use of `#[target_feature]` on safe functions. (unstable, target_feature_11, "1.45.0", Some(69098)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index b329432d1e1..36e29d2dcb2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -326,6 +326,41 @@ impl DefKind { | DefKind::ExternCrate => false, } } + + /// Whether `query struct_target_features` should be used with this definition. + pub fn has_struct_target_features(self) -> bool { + match self { + DefKind::Struct | DefKind::Union | DefKind::Enum => true, + DefKind::Fn + | DefKind::AssocFn + | DefKind::Ctor(..) + | DefKind::Closure + | DefKind::Static { .. } + | DefKind::Mod + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Const + | DefKind::AssocConst + | DefKind::Macro(..) + | DefKind::Use + | DefKind::ForeignMod + | DefKind::OpaqueTy + | DefKind::Impl { .. } + | DefKind::Field + | DefKind::TyParam + | DefKind::ConstParam + | DefKind::LifetimeParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::SyntheticCoroutineBody + | DefKind::GlobalAsm + | DefKind::ExternCrate => false, + } + } } /// The resolution of a path or export. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index dabc5a89397..54ddff98869 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -850,6 +850,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). + // FIXME(struct_target_features): should this be true also for functions that inherit + // target features from structs? if b_hdr.safety == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index eb47ac3c68e..f773b5b46ad 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,7 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", feature(extend_one, new_uninit, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))] #![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 486136a2bcc..844d8ef02e0 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -10,11 +10,11 @@ use rustc_errors::{registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, - ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, - Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, - LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, - PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, - SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + ErrorOutputType, ExternEntry, ExternLocation, Externs, FmtDebug, FunctionReturn, + InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, + LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, + OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, + ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -780,6 +780,7 @@ fn test_unstable_options_tracking_hash() { tracked!(fewer_names, Some(true)); tracked!(fixed_x18, true); tracked!(flatten_format_args, false); + tracked!(fmt_debug, FmtDebug::Shallow); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_return, FunctionReturn::ThunkExtern); @@ -794,6 +795,7 @@ fn test_unstable_options_tracking_hash() { tracked!(instrument_xray, Some(InstrumentXRay::default())); tracked!(link_directives, false); tracked!(link_only, true); + tracked!(lint_llvm_ir, true); tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 5da1cbc2283..a60fc0ffbbb 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -265,8 +265,6 @@ fn structurally_same_type_impl<'tcx>( } else { // Do a full, depth-first comparison between the two. use rustc_type_ir::TyKind::*; - let a_kind = a.kind(); - let b_kind = b.kind(); let compare_layouts = |a, b| -> Result<bool, &'tcx LayoutError<'tcx>> { debug!("compare_layouts({:?}, {:?})", a, b); @@ -281,12 +279,11 @@ fn structurally_same_type_impl<'tcx>( Ok(a_layout == b_layout) }; - #[allow(rustc::usage_of_ty_tykind)] let is_primitive_or_pointer = - |kind: &ty::TyKind<'_>| kind.is_primitive() || matches!(kind, RawPtr(..) | Ref(..)); + |ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), RawPtr(..) | Ref(..)); ensure_sufficient_stack(|| { - match (a_kind, b_kind) { + match (a.kind(), b.kind()) { (Adt(a_def, _), Adt(b_def, _)) => { // We can immediately rule out these types as structurally same if // their layouts differ. @@ -382,17 +379,21 @@ fn structurally_same_type_impl<'tcx>( // An Adt and a primitive or pointer type. This can be FFI-safe if non-null // enum layout optimisation is being applied. - (Adt(..), other_kind) | (other_kind, Adt(..)) - if is_primitive_or_pointer(other_kind) => - { - let (primitive, adt) = - if is_primitive_or_pointer(a.kind()) { (a, b) } else { (b, a) }; - if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, adt, ckind) { - ty == primitive + (Adt(..), _) if is_primitive_or_pointer(b) => { + if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, a, ckind) { + ty == b } else { compare_layouts(a, b).unwrap_or(false) } } + (_, Adt(..)) if is_primitive_or_pointer(a) => { + if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, b, ckind) { + ty == a + } else { + compare_layouts(a, b).unwrap_or(false) + } + } + // Otherwise, just compare the layouts. This may fail to lint for some // incompatible types, but at the very least, will stop reads into // uninitialised memory. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 44c72e0c4fe..04fd7c9c627 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4771,7 +4771,7 @@ declare_lint! { /// version of Rust this will be fixed and therefore dependencies relying /// on the non-spec-compliant C ABI will stop functioning. pub WASM_C_ABI, - Warn, + Deny, "detects dependencies that are incompatible with the Wasm C ABI", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 9884ed15b8a..c7306b0516f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -713,7 +713,7 @@ extern "C" LLVMRustResult LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, LLVMRustPassBuilderOptLevel OptLevelRust, LLVMRustOptStage OptStage, bool IsLinkerPluginLTO, bool NoPrepopulatePasses, bool VerifyIR, - bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, + bool LintIR, bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, @@ -842,6 +842,13 @@ extern "C" LLVMRustResult LLVMRustOptimize( }); } + if (LintIR) { + PipelineStartEPCallbacks.push_back( + [](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(createModuleToFunctionPassAdaptor(LintPass())); + }); + } + if (InstrumentGCOV) { PipelineStartEPCallbacks.push_back( [](ModulePassManager &MPM, OptimizationLevel Level) { diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 134045d0644..0f7b8921509 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -55,7 +55,7 @@ use synstructure::Structure; /// /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`: /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html> -pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream { +pub(super) fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream { s.underscore_const(true); DiagnosticDerive::new(s).into_tokens() } @@ -102,7 +102,7 @@ pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream { /// /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference> -pub fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream { +pub(super) fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream { s.underscore_const(true); LintDiagnosticDerive::new(s).into_tokens() } @@ -153,7 +153,7 @@ pub fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream { /// /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident }); /// ``` -pub fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream { +pub(super) fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream { s.underscore_const(true); SubdiagnosticDerive::new().into_tokens(s) } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 929bc2df6f6..f46c795b956 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -6,6 +6,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![feature(proc_macro_tracked_env)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs index 627f4088d5f..bf4a7665ceb 100644 --- a/compiler/rustc_macros/src/lift.rs +++ b/compiler/rustc_macros/src/lift.rs @@ -1,7 +1,7 @@ use quote::quote; use syn::parse_quote; -pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { s.add_bounds(synstructure::AddBounds::Generics); s.bind_with(|_| synstructure::BindStyle::Move); s.underscore_const(true); diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index ceff1da9763..886a38c8ff2 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -307,7 +307,7 @@ fn add_query_desc_cached_impl( }); } -pub fn rustc_queries(input: TokenStream) -> TokenStream { +pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { let queries = parse_macro_input!(input as List<Query>); let mut query_stream = quote! {}; diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 7b5dd1601c1..2c33a0ac0aa 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -3,7 +3,9 @@ use quote::{quote, quote_spanned}; use syn::parse_quote; use syn::spanned::Spanned; -pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn type_decodable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } @@ -20,7 +22,9 @@ pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: decodable_body(s, decoder_ty) } -pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn meta_decodable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { s.add_impl_generic(parse_quote! { 'tcx }); } @@ -32,7 +36,7 @@ pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: decodable_body(s, decoder_ty) } -pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_span::SpanDecoder }); s.add_bounds(synstructure::AddBounds::Generics); @@ -41,7 +45,9 @@ pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke decodable_body(s, decoder_ty) } -pub fn decodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn decodable_generic_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder }); s.add_bounds(synstructure::AddBounds::Generics); @@ -123,7 +129,9 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { quote_spanned! { field_span=> #decode_inner_method(#__decoder) } } -pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn type_encodable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { @@ -140,7 +148,9 @@ pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: encodable_body(s, encoder_ty, false) } -pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn meta_encodable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { s.add_impl_generic(parse_quote! { 'tcx }); } @@ -152,7 +162,7 @@ pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: encodable_body(s, encoder_ty, true) } -pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let encoder_ty = quote! { __E }; s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_span::SpanEncoder }); s.add_bounds(synstructure::AddBounds::Generics); @@ -161,7 +171,9 @@ pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke encodable_body(s, encoder_ty, false) } -pub fn encodable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn encodable_generic_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { let encoder_ty = quote! { __E }; s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder }); s.add_bounds(synstructure::AddBounds::Generics); diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 6074c93d59c..341186ac1ca 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -131,7 +131,7 @@ impl Errors { } } -pub fn symbols(input: TokenStream) -> TokenStream { +pub(super) fn symbols(input: TokenStream) -> TokenStream { let (mut output, errors) = symbols_with_errors(input); // If we generated any errors, then report them as compiler_error!() macro calls. diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 5617c53b119..8ddfa96e095 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,7 +1,7 @@ use quote::{quote, ToTokens}; use syn::parse_quote; -pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { panic!("cannot derive on union") } diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index 94e86e0e246..527ca26c0eb 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -1,7 +1,9 @@ use quote::quote; use syn::parse_quote; -pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(super) fn type_visitable_derive( + mut s: synstructure::Structure<'_>, +) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { panic!("cannot derive on union") } diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index acaf9fb0fc3..58b352f263d 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -3,6 +3,7 @@ #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(control_flow_enum)] #![feature(coroutines)] #![feature(decl_macro)] #![feature(error_iter)] @@ -16,6 +17,7 @@ #![feature(proc_macro_internals)] #![feature(rustdoc_internals)] #![feature(trusted_len)] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate proc_macro; @@ -34,7 +36,9 @@ pub mod locator; pub use creader::{load_symbol_from_dylib, DylibError}; pub use fs::{emit_wrapper_file, METADATA_FILENAME}; -pub use native_libs::find_native_static_library; +pub use native_libs::{ + find_native_static_library, try_find_native_static_library, walk_native_lib_search_dirs, +}; pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER}; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 34497f5ac53..a6ad449cb53 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,4 +1,5 @@ -use std::path::PathBuf; +use std::ops::ControlFlow; +use std::path::{Path, PathBuf}; use rustc_ast::{NestedMetaItem, CRATE_NODE_ID}; use rustc_attr as attr; @@ -16,10 +17,68 @@ use rustc_session::Session; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; +use rustc_target::spec::LinkSelfContainedComponents; use crate::{errors, fluent_generated}; -pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { +pub fn walk_native_lib_search_dirs<R>( + sess: &Session, + self_contained_components: LinkSelfContainedComponents, + apple_sdk_root: Option<&Path>, + mut f: impl FnMut(&Path, bool /*is_framework*/) -> ControlFlow<R>, +) -> ControlFlow<R> { + // Library search paths explicitly supplied by user (`-L` on the command line). + for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() { + f(&search_path.dir, false)?; + } + for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() { + // Frameworks are looked up strictly in framework-specific paths. + if search_path.kind != PathKind::All { + f(&search_path.dir, true)?; + } + } + + // The toolchain ships some native library components and self-contained linking was enabled. + // Add the self-contained library directory to search paths. + if self_contained_components.intersects( + LinkSelfContainedComponents::LIBC + | LinkSelfContainedComponents::UNWIND + | LinkSelfContainedComponents::MINGW, + ) { + f(&sess.target_tlib_path.dir.join("self-contained"), false)?; + } + + // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot + // library directory instead of the self-contained directories. + // Sanitizer libraries have the same issue and are also linked by name on Apple targets. + // The targets here should be in sync with `copy_third_party_objects` in bootstrap. + // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind + // and sanitizers to self-contained directory, and stop adding this search path. + if sess.target.vendor == "fortanix" + || sess.target.os == "linux" + || sess.target.os == "fuchsia" + || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() + { + f(&sess.target_tlib_path.dir, false)?; + } + + // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks + // we must have the support library stubs in the library search path (#121430). + if let Some(sdk_root) = apple_sdk_root + && sess.target.llvm_target.contains("macabi") + { + f(&sdk_root.join("System/iOSSupport/usr/lib"), false)?; + f(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"), true)?; + } + + ControlFlow::Continue(()) +} + +pub fn try_find_native_static_library( + sess: &Session, + name: &str, + verbatim: bool, +) -> Option<PathBuf> { let formats = if verbatim { vec![("".into(), "".into())] } else { @@ -30,16 +89,29 @@ pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> if os == unix { vec![os] } else { vec![os, unix] } }; - for path in sess.target_filesearch(PathKind::Native).search_paths() { - for (prefix, suffix) in &formats { - let test = path.dir.join(format!("{prefix}{name}{suffix}")); - if test.exists() { - return test; + // FIXME: Account for self-contained linking settings and Apple SDK. + walk_native_lib_search_dirs( + sess, + LinkSelfContainedComponents::empty(), + None, + |dir, is_framework| { + if !is_framework { + for (prefix, suffix) in &formats { + let test = dir.join(format!("{prefix}{name}{suffix}")); + if test.exists() { + return ControlFlow::Break(test); + } + } } - } - } + ControlFlow::Continue(()) + }, + ) + .break_value() +} - sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)); +pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { + try_find_native_static_library(sess, name, verbatim) + .unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim))) } fn find_bundled_library( diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a13eac08c9f..f3ae24a5895 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -56,13 +56,13 @@ impl std::ops::Deref for MetadataBlob { impl MetadataBlob { /// Runs the [`MemDecoder`] validation and if it passes, constructs a new [`MetadataBlob`]. - pub fn new(slice: OwnedSlice) -> Result<Self, ()> { + pub(crate) fn new(slice: OwnedSlice) -> Result<Self, ()> { if MemDecoder::new(&slice, 0).is_ok() { Ok(Self(slice)) } else { Err(()) } } /// Since this has passed the validation of [`MetadataBlob::new`], this returns bytes which are /// known to pass the [`MemDecoder`] validation. - pub fn bytes(&self) -> &OwnedSlice { + pub(crate) fn bytes(&self) -> &OwnedSlice { &self.0 } } @@ -332,12 +332,12 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { } #[inline] - pub fn blob(&self) -> &'a MetadataBlob { + pub(crate) fn blob(&self) -> &'a MetadataBlob { self.blob } #[inline] - pub fn cdata(&self) -> CrateMetadataRef<'a> { + fn cdata(&self) -> CrateMetadataRef<'a> { debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext"); self.cdata.unwrap() } @@ -377,7 +377,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { } #[inline] - pub fn read_raw_bytes(&mut self, len: usize) -> &[u8] { + fn read_raw_bytes(&mut self, len: usize) -> &[u8] { self.opaque.read_raw_bytes(len) } } @@ -962,7 +962,7 @@ impl CrateRoot { } } -impl<'a, 'tcx> CrateMetadataRef<'a> { +impl<'a> CrateMetadataRef<'a> { fn missing(self, descr: &str, id: DefIndex) -> ! { bug!("missing `{descr}` for {:?}", self.local_def_id(id)) } @@ -1036,7 +1036,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn load_proc_macro(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { + fn load_proc_macro<'tcx>(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> SyntaxExtension { let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = @@ -1070,34 +1070,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_explicit_item_bounds( - self, - index: DefIndex, - tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - let lazy = self.root.tables.explicit_item_bounds.get(self, index); - let output = if lazy.is_default() { - &mut [] - } else { - tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) - }; - ty::EarlyBinder::bind(&*output) - } - - fn get_explicit_item_super_predicates( - self, - index: DefIndex, - tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - let lazy = self.root.tables.explicit_item_super_predicates.get(self, index); - let output = if lazy.is_default() { - &mut [] - } else { - tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) - }; - ty::EarlyBinder::bind(&*output) - } - fn get_variant( self, kind: DefKind, @@ -1141,7 +1113,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { + fn get_adt_def<'tcx>(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::AdtDef<'tcx> { let kind = self.def_kind(item_id); let did = self.local_def_id(item_id); @@ -1225,12 +1197,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute /// has an `implied_by` meta item, then the mapping from the implied feature to the actual /// feature is a stability implication). - fn get_stability_implications(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { + fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { tcx.arena.alloc_from_iter(self.root.stability_implications.decode(self)) } /// Iterates over the lang items in the given crate. - fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { + fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { tcx.arena.alloc_from_iter( self.root .lang_items @@ -1239,7 +1211,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_stripped_cfg_items(self, cnum: CrateNum, tcx: TyCtxt<'tcx>) -> &'tcx [StrippedCfgItem] { + fn get_stripped_cfg_items<'tcx>( + self, + cnum: CrateNum, + tcx: TyCtxt<'tcx>, + ) -> &'tcx [StrippedCfgItem] { let item_names = self .root .stripped_cfg_items @@ -1319,10 +1295,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.optimized_mir.get(self, id).is_some() } - fn cross_crate_inlinable(self, id: DefIndex) -> bool { - self.root.tables.cross_crate_inlinable.get(self, id) - } - fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { self.root .tables @@ -1412,7 +1384,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_inherent_implementations_for_type( + fn get_inherent_implementations_for_type<'tcx>( self, tcx: TyCtxt<'tcx>, id: DefIndex, @@ -1439,7 +1411,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn get_incoherent_impls(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { + fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { if let Some(impls) = self.cdata.incoherent_impls.get(&simp) { tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) } else { @@ -1447,7 +1419,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } - fn get_implementations_of_trait( + fn get_implementations_of_trait<'tcx>( self, tcx: TyCtxt<'tcx>, trait_def_id: DefId, @@ -1491,7 +1463,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.foreign_modules.decode((self, sess)) } - fn get_dylib_dependency_formats( + fn get_dylib_dependency_formats<'tcx>( self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { @@ -1503,11 +1475,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { + fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) } - fn exported_symbols( + fn exported_symbols<'tcx>( self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 2815c5c2390..a82340e3d61 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -32,13 +32,20 @@ trait ProcessQueryValue<'tcx, T> { fn process_decoded(self, _tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> T; } -impl<T> ProcessQueryValue<'_, Option<T>> for Option<T> { +impl<T> ProcessQueryValue<'_, T> for T { #[inline(always)] - fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> Option<T> { + fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> T { self } } +impl<'tcx, T> ProcessQueryValue<'tcx, ty::EarlyBinder<'tcx, T>> for T { + #[inline(always)] + fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> ty::EarlyBinder<'tcx, T> { + ty::EarlyBinder::bind(self) + } +} + impl<T> ProcessQueryValue<'_, T> for Option<T> { #[inline(always)] fn process_decoded(self, _tcx: TyCtxt<'_>, err: impl Fn() -> !) -> T { @@ -121,7 +128,12 @@ macro_rules! provide_one { provide_one! { $tcx, $def_id, $other, $cdata, $name => { let lazy = $cdata.root.tables.$name.get($cdata, $def_id.index); - if lazy.is_default() { &[] } else { $tcx.arena.alloc_from_iter(lazy.decode(($cdata, $tcx))) } + let value = if lazy.is_default() { + &[] as &[_] + } else { + $tcx.arena.alloc_from_iter(lazy.decode(($cdata, $tcx))) + }; + value.process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name))) } } }; @@ -230,18 +242,19 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } provide! { tcx, def_id, other, cdata, - explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } - explicit_item_super_predicates => { cdata.get_explicit_item_super_predicates(def_id.index, tcx) } + explicit_item_bounds => { table_defaulted_array } + explicit_item_super_predicates => { table_defaulted_array } explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } explicit_super_predicates_of => { table } explicit_implied_predicates_of => { table } type_of => { table } - type_alias_is_lazy => { cdata.root.tables.type_alias_is_lazy.get(cdata, def_id.index) } + type_alias_is_lazy => { table_direct } variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } + struct_target_features => { table } impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } @@ -258,7 +271,7 @@ provide! { tcx, def_id, other, cdata, lookup_default_body_stability => { table } lookup_deprecation_entry => { table } params_in_repr => { table } - unused_generic_params => { cdata.root.tables.unused_generic_params.get(cdata, def_id.index) } + unused_generic_params => { table_direct } def_kind => { cdata.def_kind(def_id.index) } impl_parent => { table } defaultness => { table_direct } @@ -304,9 +317,7 @@ provide! { tcx, def_id, other, cdata, .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) } - associated_type_for_effects => { - table - } + associated_type_for_effects => { table } associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array } visibility => { cdata.get_visibility(def_id.index) } @@ -327,7 +338,7 @@ provide! { tcx, def_id, other, cdata, item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } - cross_crate_inlinable => { cdata.cross_crate_inlinable(def_id.index) } + cross_crate_inlinable => { table_direct } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_private_dep => { cdata.private_dep } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 01fbf37788f..19369425f81 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -17,7 +17,7 @@ parameterized_over_tcx! { impl DefPathHashMapRef<'_> { #[inline] - pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { + pub(crate) fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { match *self { DefPathHashMapRef::OwnedFromMetadata(ref map) => { map.get(&def_path_hash.local_hash()).unwrap() diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3fd6abbb363..919623cff60 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1392,6 +1392,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } + if def_kind.has_struct_target_features() { + record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id)); + } if should_encode_visibility(def_kind) { let vis = self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); @@ -2310,7 +2313,7 @@ fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Erro Ok(()) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { doc_link_resolutions: |tcx, def_id| { tcx.resolutions(()) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a84923130c3..987ee3f07e9 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_macros::{ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; @@ -427,6 +427,7 @@ define_tables! { variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, + struct_target_features: Table<DefIndex, LazyArray<TargetFeature>>, impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>, const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, rustc_middle::ty::Const<'static>>>>, object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 37c10b14054..7050a06b8dc 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -35,7 +35,6 @@ macro_rules! arena_types { )>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, - [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, [] region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 9ebe4a57b02..2d47d1d19af 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -61,8 +61,9 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LO use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; pub use rustc_query_system::dep_graph::dep_node::DepKind; +pub use rustc_query_system::dep_graph::DepNode; use rustc_query_system::dep_graph::FingerprintStyle; -pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams}; +pub(crate) use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; use rustc_span::symbol::Symbol; use crate::mir::mono::MonoItem; @@ -101,7 +102,7 @@ macro_rules! define_dep_nodes { // This checks that the discriminants of the variants have been assigned consecutively // from 0 so that they can be used as a dense index. - pub const DEP_KIND_VARIANTS: u16 = { + pub(crate) const DEP_KIND_VARIANTS: u16 = { let deps = &[$(dep_kinds::$variant,)*]; let mut i = 0; while i < deps.len() { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ce330b4744b..2a85f85a9f4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -53,7 +53,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(new_uninit)] #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] @@ -63,6 +62,7 @@ #![feature(try_blocks)] #![feature(type_alias_impl_trait)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end #[cfg(test)] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b7d290e58d2..c098a739592 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,8 @@ pub struct CodegenFnAttrs { /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option<u16>, - /// The `#[target_feature(enable = "...")]` attribute and the enabled - /// features (only enabled features are supported right now). + /// All the target features that are enabled for this function. Some features might be enabled + /// implicitly. pub target_features: Vec<TargetFeature>, /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option<Linkage>, @@ -55,8 +55,8 @@ pub struct CodegenFnAttrs { pub struct TargetFeature { /// The name of the target feature (e.g. "avx") pub name: Symbol, - /// The feature is implied by another feature, rather than explicitly added by the - /// `#[target_feature]` attribute + /// The feature is implied by another feature or by an argument, rather than explicitly + /// added by the `#[target_feature]` attribute pub implied: bool, } diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index c08bfc1fa95..183b898253e 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -18,9 +18,9 @@ pub struct BasicBlocks<'tcx> { } // Typically 95%+ of basic blocks have 4 or fewer predecessors. -pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>; +type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>; -pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>; +type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>; #[derive(Clone, Default, Debug)] struct Cache { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index b11c523cfe9..bfe2a2c2cb3 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -163,7 +163,7 @@ impl Debug for CoverageKind { #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] #[derive(TypeFoldable, TypeVisitable)] -pub struct CodeRegion { +pub struct SourceRegion { pub file_name: Symbol, pub start_line: u32, pub start_col: u32, @@ -171,7 +171,7 @@ pub struct CodeRegion { pub end_col: u32, } -impl Debug for CodeRegion { +impl Debug for SourceRegion { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!( fmt, @@ -242,7 +242,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub code_region: CodeRegion, + pub source_region: SourceRegion, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs index 51e26ab7984..a52ec58a1ee 100644 --- a/compiler/rustc_middle/src/mir/generic_graph.rs +++ b/compiler/rustc_middle/src/mir/generic_graph.rs @@ -2,7 +2,7 @@ use gsgdt::{Edge, Graph, Node, NodeStyle}; use rustc_middle::mir::*; /// Convert an MIR function into a gsgdt Graph -pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph { +pub(crate) fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph { let def_id = body.source.def_id(); let def_name = graphviz_safe_def_name(def_id); let graph_name = format!("Mir_{def_name}"); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs index 1d2a82c575a..dfaf96e14f6 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs @@ -243,7 +243,7 @@ impl hash::Hash for InitMaskMaterialized { } impl InitMaskMaterialized { - pub const BLOCK_SIZE: u64 = 64; + const BLOCK_SIZE: u64 = 64; fn new(size: Size, state: bool) -> Self { let mut m = InitMaskMaterialized { blocks: vec![] }; diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 1d94c364ae3..69b5e0a79c7 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -396,7 +396,7 @@ impl<'tcx> CodegenUnit<'tcx> { // The codegen tests rely on items being process in the same order as // they appear in the file, so for local items, we sort by node_id first #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct ItemSortKey<'tcx>(Option<usize>, SymbolName<'tcx>); + struct ItemSortKey<'tcx>(Option<usize>, SymbolName<'tcx>); fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { ItemSortKey( diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index efdc0c710ba..6785805c27d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -547,8 +547,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, code_region } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {code_region:?};")?; + for coverage::Mapping { kind, source_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d6bdc1af0d2..b6443778c93 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,7 +47,7 @@ use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::CodegenFnAttrs; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; @@ -1249,6 +1249,11 @@ rustc_queries! { feedable } + query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] { + separate_provide_extern + desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) } + } + query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 401f6da6526..46203ee150f 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -462,7 +462,6 @@ impl_decodable_via_ref! { &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion, &'tcx ty::List<ty::BoundVariableKind>, &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>, &'tcx ty::List<FieldIdx>, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 59cacc5ef41..d6dbad9dab8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2188,7 +2188,7 @@ macro_rules! sty_debug_print { all_infer: usize, } - pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result { + pub(crate) fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result { let mut total = DebugStat { total: 0, lt_infer: 0, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 7e1255f606c..be611e19b49 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, + crate::middle::codegen_fn_attrs::TargetFeature, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::lib_features::FeatureStability, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d60bfb9faa1..c6621a7a643 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1000,7 +1000,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_primitive(self) -> bool { - self.kind().is_primitive() + matches!(self.kind(), Bool | Char | Int(_) | Uint(_) | Float(_)) } #[inline] diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 7a10e627ccd..a42e8ff0168 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -125,6 +125,17 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + +mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + initializing type with `target_feature` attr is unsafe and requires unsafe function or block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + + mir_build_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior @@ -387,6 +398,11 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr +mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe = + initializing type with `target_feature` attr is unsafe and requires unsafe block + .note = this struct can only be constructed if the corresponding `target_feature`s are available + .label = initializing type with `target_feature` attr + mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b6cf7a40ecd..4ce796cea7a 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -461,14 +461,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id)); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { - // If the called function has target features the calling function hasn't, + // If the called function has explicit target features the calling function hasn't, // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs + // Implicit target features are OK because they are either a consequence of some + // explicit target feature (which is checked to be present in the caller) or + // come from a witness argument. let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm && !callee_features.iter().all(|feature| { - self.body_target_features.iter().any(|f| f.name == feature.name) + feature.implied + || self.body_target_features.iter().any(|f| f.name == feature.name) }) { let missing: Vec<_> = callee_features @@ -542,10 +546,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { user_ty: _, fields: _, base: _, - }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.requires_unsafe(expr.span, InitializingTypeWith), - }, + }) => { + match self.tcx.layout_scalar_valid_range(adt_def.did()) { + (Bound::Unbounded, Bound::Unbounded) => {} + _ => self.requires_unsafe(expr.span, InitializingTypeWith), + } + if !self.tcx.struct_target_features(adt_def.did()).is_empty() { + self.requires_unsafe(expr.span, ConstructingTargetFeaturesType) + } + } + ExprKind::Closure(box ClosureExpr { closure_id, args: _, @@ -647,6 +657,7 @@ enum UnsafeOpKind { CallToUnsafeFunction(Option<DefId>), UseOfInlineAssembly, InitializingTypeWith, + ConstructingTargetFeaturesType, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -728,6 +739,15 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), + ConstructingTargetFeaturesType => tcx.emit_node_span_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, + ), UseOfMutableStatic => tcx.emit_node_span_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, @@ -885,6 +905,20 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } + ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => { + dcx.emit_err( + InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, + ); + } + ConstructingTargetFeaturesType => { + dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); + } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, @@ -993,7 +1027,7 @@ impl UnsafeOpKind { } } -pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { +pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { // Closures and inline consts are handled by their owner, if it has a body // Also, don't safety check custom MIR if tcx.is_typeck_child(def.to_def_id()) || tcx.has_attr(def, sym::custom_mir) { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 7f9eefd1d52..e7d6239aa9b 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -87,6 +87,16 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { } #[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, +} + +#[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { @@ -251,6 +261,17 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe { } #[derive(Diagnostic)] +#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, +} + +#[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133 @@ -265,6 +286,20 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { } #[derive(Diagnostic)] +#[diag( + mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = E0133 +)] +#[note] +pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub(crate) span: Span, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, +} + +#[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] pub(crate) struct UseOfMutableStaticRequiresUnsafe { diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 66004179b10..3dbb552cdbb 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -8,6 +8,7 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod build; diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 364a416480f..0bab03b0271 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -24,7 +24,7 @@ use crate::errors::{ }; use crate::framework::BitSetExt; -pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>; +type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>; /// A dataflow analysis that has converged to fixpoint. #[derive(Clone)] diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 6eaed0f7753..6da3a20dc02 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -510,7 +510,7 @@ impl<T: Idx> GenKill<T> for lattice::Dual<BitSet<T>> { // NOTE: DO NOT CHANGE VARIANT ORDER. The derived `Ord` impls rely on the current order. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Effect { +enum Effect { /// The "before" effect (e.g., `apply_before_statement_effect`) for a statement (or /// terminator). Before, @@ -520,7 +520,7 @@ pub enum Effect { } impl Effect { - pub const fn at_index(self, statement_index: usize) -> EffectIndex { + const fn at_index(self, statement_index: usize) -> EffectIndex { EffectIndex { effect: self, statement_index } } } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 8708bebeeb0..9385b52103f 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -5,6 +5,7 @@ #![feature(exact_size_is_empty)] #![feature(let_chains)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::ty; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs index 2a7f23ef6d2..df4c0593246 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs @@ -15,12 +15,12 @@ use rustc_middle::mir::{Local, Operand, PlaceElem, ProjectionElem}; use rustc_middle::ty::Ty; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct AbstractOperand; +pub(crate) struct AbstractOperand; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct AbstractType; -pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>; +pub(crate) struct AbstractType; +pub(crate) type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>; -pub trait Lift { +pub(crate) trait Lift { type Abstract; fn lift(&self) -> Self::Abstract; } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 96ca3b43d5c..af0f1e38a75 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,7 +13,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CodeRegion, CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, @@ -159,7 +159,7 @@ fn create_mappings<'tcx>( .expect("all BCBs with spans were given counters") .as_term() }; - let region_for_span = |span: Span| make_code_region(source_map, file_name, span, body_span); + let region_for_span = |span: Span| make_source_region(source_map, file_name, span, body_span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -175,9 +175,9 @@ fn create_mappings<'tcx>( mappings.extend(code_mappings.iter().filter_map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -186,29 +186,29 @@ fn create_mappings<'tcx>( let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - let code_region = region_for_span(span)?; - Some(Mapping { kind, code_region }) + let source_region = region_for_span(span)?; + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_branches.iter().filter_map( |&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = match condition_info { Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params }, None => MappingKind::Branch { true_term, false_term }, }; - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); mappings.extend(mcdc_decisions.iter().filter_map( |&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| { - let code_region = region_for_span(span)?; + let source_region = region_for_span(span)?; let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions }); - Some(Mapping { kind, code_region }) + Some(Mapping { kind, source_region }) }, )); @@ -362,19 +362,13 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -fn make_code_region( +#[instrument(level = "debug", skip(source_map))] +fn make_source_region( source_map: &SourceMap, file_name: Symbol, span: Span, body_span: Span, -) -> Option<CodeRegion> { - debug!( - "Called make_code_region(file_name={}, span={}, body_span={})", - file_name, - source_map.span_to_diagnostic_string(span), - source_map.span_to_diagnostic_string(body_span) - ); - +) -> Option<SourceRegion> { let lo = span.lo(); let hi = span.hi(); @@ -424,7 +418,7 @@ fn make_code_region( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - check_code_region(CodeRegion { + check_source_region(SourceRegion { file_name, start_line: start_line as u32, start_col: start_col as u32, @@ -433,12 +427,12 @@ fn make_code_region( }) } -/// If `llvm-cov` sees a code region that is improperly ordered (end < start), +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. -fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> { - let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; +fn check_source_region(source_region: SourceRegion) -> Option<SourceRegion> { + let SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = source_region; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. @@ -451,17 +445,17 @@ fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> { let is_ordered = (start_line, start_col) <= (end_line, end_col); if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(code_region) + Some(source_region) } else { debug!( - ?code_region, + ?source_region, ?all_nonzero, ?end_col_has_high_bit_unset, ?is_ordered, - "Skipping code region that would be misinterpreted or rejected by LLVM" + "Skipping source region that would be misinterpreted or rejected by LLVM" ); // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper code region: {code_region:?}"); + debug_assert!(false, "Improper source region: {source_region:?}"); None } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index f207216d6f4..03b1d426df4 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -382,7 +382,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { place: PlaceIndex, mut operand: OpTy<'tcx>, projection: &[PlaceElem<'tcx>], - ) -> Option<!> { + ) { for &(mut proj_elem) in projection { if let PlaceElem::Index(index) = proj_elem { if let FlatSet::Elem(index) = state.get(index.into(), &self.map) @@ -391,10 +391,14 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { { proj_elem = PlaceElem::ConstantIndex { offset, min_length, from_end: false }; } else { - return None; + return; } } - operand = self.ecx.project(&operand, proj_elem).ok()?; + operand = if let Ok(operand) = self.ecx.project(&operand, proj_elem) { + operand + } else { + return; + } } self.map.for_each_projection_value( @@ -426,8 +430,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } }, ); - - None } fn binary_op( diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 56e8905bead..c65cc993b19 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -135,6 +135,14 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( } false } + // FIXME(-Znext-solver): Remove this hack when trait solver overflow can return an error. + // In code like that pointed out in #128887, the type complexity we ask the solver to deal with + // grows as we recurse into the call graph. If we use the same recursion limit here and in the + // solver, the solver hits the limit first and emits a fatal error. But if we use a reduced + // limit, we will hit the limit first and give up on looking for inlining. And in any case, + // the default recursion limits are quite generous for us. If we need to recurse 64 times + // into the call graph, we're probably not going to find any useful MIR inlining. + let recursion_limit = tcx.recursion_limit() / 2; process( tcx, param_env, @@ -143,7 +151,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( &mut Vec::new(), &mut FxHashSet::default(), &mut FxHashMap::default(), - tcx.recursion_limit(), + recursion_limit, ) } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 96c52845a4a..8997b1d57cd 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -191,26 +191,26 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { /// Recursion entry point to find threading opportunities. #[instrument(level = "trace", skip(self))] - fn start_from_switch(&mut self, bb: BasicBlock) -> Option<!> { + fn start_from_switch(&mut self, bb: BasicBlock) { let bbdata = &self.body[bb]; if bbdata.is_cleanup || self.loop_headers.contains(bb) { - return None; + return; } - let (discr, targets) = bbdata.terminator().kind.as_switch()?; - let discr = discr.place()?; + let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return }; + let Some(discr) = discr.place() else { return }; debug!(?discr, ?bb); let discr_ty = discr.ty(self.body, self.tcx).ty; - let discr_layout = self.ecx.layout_of(discr_ty).ok()?; + let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; - let discr = self.map.find(discr.as_ref())?; + let Some(discr) = self.map.find(discr.as_ref()) else { return }; debug!(?discr); let cost = CostChecker::new(self.tcx, self.param_env, None, self.body); let mut state = State::new_reachable(); let conds = if let Some((value, then, else_)) = targets.as_static_if() { - let value = ScalarInt::try_from_uint(value, discr_layout.size)?; + let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; self.arena.alloc_from_iter([ Condition { value, polarity: Polarity::Eq, target: then }, Condition { value, polarity: Polarity::Ne, target: else_ }, @@ -225,7 +225,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { state.insert_value_idx(discr, conds, self.map); self.find_opportunity(bb, state, cost, 0); - None } /// Recursively walk statements backwards from this bb's terminator to find threading @@ -364,18 +363,17 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { lhs: PlaceIndex, rhs: ImmTy<'tcx>, state: &mut State<ConditionSet<'a>>, - ) -> Option<!> { + ) { let register_opportunity = |c: Condition| { debug!(?bb, ?c.target, "register"); self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) }; - let conditions = state.try_get_idx(lhs, self.map)?; - if let Immediate::Scalar(Scalar::Int(int)) = *rhs { + if let Some(conditions) = state.try_get_idx(lhs, self.map) + && let Immediate::Scalar(Scalar::Int(int)) = *rhs + { conditions.iter_matches(int).for_each(register_opportunity); } - - None } /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. @@ -428,22 +426,23 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { lhs: PlaceIndex, rhs: &Operand<'tcx>, state: &mut State<ConditionSet<'a>>, - ) -> Option<!> { + ) { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let constant = - self.ecx.eval_mir_constant(&constant.const_, constant.span, None).ok()?; + let Ok(constant) = + self.ecx.eval_mir_constant(&constant.const_, constant.span, None) + else { + return; + }; self.process_constant(bb, lhs, constant, state); } // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { - let rhs = self.map.find(rhs.as_ref())?; + let Some(rhs) = self.map.find(rhs.as_ref()) else { return }; state.insert_place_idx(rhs, lhs, self.map); } } - - None } #[instrument(level = "trace", skip(self))] @@ -453,16 +452,14 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { lhs_place: &Place<'tcx>, rhs: &Rvalue<'tcx>, state: &mut State<ConditionSet<'a>>, - ) -> Option<!> { - let lhs = self.map.find(lhs_place.as_ref())?; + ) { + let Some(lhs) = self.map.find(lhs_place.as_ref()) else { return }; match rhs { - Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, + Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state), // Transfer the conditions on the copy rhs. - Rvalue::CopyForDeref(rhs) => { - self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? - } + Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state), Rvalue::Discriminant(rhs) => { - let rhs = self.map.find_discr(rhs.as_ref())?; + let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return }; state.insert_place_idx(rhs, lhs, self.map); } // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. @@ -470,7 +467,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let agg_ty = lhs_place.ty(self.body, self.tcx).ty; let lhs = match kind { // Do not support unions. - AggregateKind::Adt(.., Some(_)) => return None, + AggregateKind::Adt(.., Some(_)) => return, AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) && let Ok(discr_value) = @@ -478,7 +475,11 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { { self.process_immediate(bb, discr_target, discr_value, state); } - self.map.apply(lhs, TrackElem::Variant(*variant_index))? + if let Some(idx) = self.map.apply(lhs, TrackElem::Variant(*variant_index)) { + idx + } else { + return; + } } _ => lhs, }; @@ -490,8 +491,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } // Transfer the conditions on the copy rhs, after inversing polarity. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; + let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(place) = self.map.find(place.as_ref()) else { return }; let conds = conditions.map(self.arena, Condition::inv); state.insert_value_idx(place, conds, self.map); } @@ -502,21 +503,25 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), ) => { - let conditions = state.try_get_idx(lhs, self.map)?; - let place = self.map.find(place.as_ref())?; + let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(place) = self.map.find(place.as_ref()) else { return }; let equals = match op { BinOp::Eq => ScalarInt::TRUE, BinOp::Ne => ScalarInt::FALSE, - _ => return None, + _ => return, }; if value.const_.ty().is_floating_point() { // Floating point equality does not follow bit-patterns. // -0.0 and NaN both have special rules for equality, // and therefore we cannot use integer comparisons for them. // Avoid handling them, though this could be extended in the future. - return None; + return; } - let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?; + let Some(value) = + value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int() + else { + return; + }; let conds = conditions.map(self.arena, |c| Condition { value, polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, @@ -527,8 +532,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { _ => {} } - - None } #[instrument(level = "trace", skip(self))] @@ -537,7 +540,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { bb: BasicBlock, stmt: &Statement<'tcx>, state: &mut State<ConditionSet<'a>>, - ) -> Option<!> { + ) { let register_opportunity = |c: Condition| { debug!(?bb, ?c.target, "register"); self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) @@ -550,12 +553,12 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // If we expect `discriminant(place) ?= A`, // we have an opportunity if `variant_index ?= A`. StatementKind::SetDiscriminant { box place, variant_index } => { - let discr_target = self.map.find_discr(place.as_ref())?; + let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return }; let enum_ty = place.ty(self.body, self.tcx).ty; // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant // of a niche encoding. If we cannot ensure that we write to the discriminant, do // nothing. - let enum_layout = self.ecx.layout_of(enum_ty).ok()?; + let Ok(enum_layout) = self.ecx.layout_of(enum_ty) else { return }; let writes_discriminant = match enum_layout.variants { Variants::Single { index } => { assert_eq!(index, *variant_index); @@ -568,24 +571,25 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } => *variant_index != untagged_variant, }; if writes_discriminant { - let discr = self.ecx.discriminant_for_variant(enum_ty, *variant_index).ok()?; - self.process_immediate(bb, discr_target, discr, state)?; + let Ok(discr) = self.ecx.discriminant_for_variant(enum_ty, *variant_index) + else { + return; + }; + self.process_immediate(bb, discr_target, discr, state); } } // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`. StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume( Operand::Copy(place) | Operand::Move(place), )) => { - let conditions = state.try_get(place.as_ref(), self.map)?; + let Some(conditions) = state.try_get(place.as_ref(), self.map) else { return }; conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { - self.process_assign(bb, lhs_place, rhs, state)?; + self.process_assign(bb, lhs_place, rhs, state); } _ => {} } - - None } #[instrument(level = "trace", skip(self, state, cost))] @@ -638,17 +642,17 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { targets: &SwitchTargets, target_bb: BasicBlock, state: &mut State<ConditionSet<'a>>, - ) -> Option<!> { + ) { debug_assert_ne!(target_bb, START_BLOCK); debug_assert_eq!(self.body.basic_blocks.predecessors()[target_bb].len(), 1); - let discr = discr.place()?; + let Some(discr) = discr.place() else { return }; let discr_ty = discr.ty(self.body, self.tcx).ty; - let discr_layout = self.ecx.layout_of(discr_ty).ok()?; - let conditions = state.try_get(discr.as_ref(), self.map)?; + let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; + let Some(conditions) = state.try_get(discr.as_ref(), self.map) else { return }; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { - let value = ScalarInt::try_from_uint(value, discr_layout.size)?; + let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; debug_assert_eq!(targets.iter().filter(|&(_, target)| target == target_bb).count(), 1); // We are inside `target_bb`. Since we have a single predecessor, we know we passed @@ -662,7 +666,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } else if let Some((value, _, else_bb)) = targets.as_static_if() && target_bb == else_bb { - let value = ScalarInt::try_from_uint(value, discr_layout.size)?; + let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; // We only know that `discr != value`. That's much weaker information than // the equality we had in the previous arm. All we can conclude is that @@ -675,8 +679,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } } } - - None } } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 7eed47cf239..3427b93c1f6 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -469,12 +469,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { msg: &AssertKind<Operand<'tcx>>, cond: &Operand<'tcx>, location: Location, - ) -> Option<!> { - let value = &self.eval_operand(cond)?; + ) { + let Some(value) = &self.eval_operand(cond) else { return }; trace!("assertion on {:?} should be {:?}", value, expected); let expected = Scalar::from_bool(expected); - let value_const = self.use_ecx(|this| this.ecx.read_scalar(value))?; + let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value)) else { return }; if expected != value_const { // Poison all places this operand references so that further code @@ -516,14 +516,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { AssertKind::BoundsCheck { len, index } } // Remaining overflow errors are already covered by checks on the binary operators. - AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) => return None, + AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) => return, // Need proper const propagator for these. - _ => return None, + _ => return, }; self.report_assert_as_lint(location, AssertLintKind::UnconditionalPanic, msg); } - - None } fn ensure_not_propagated(&self, local: Local) { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 36fb2e89af1..9c820b888d9 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -242,12 +242,12 @@ use tracing::{debug, instrument, trace}; use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit}; #[derive(PartialEq)] -pub enum MonoItemCollectionStrategy { +pub(crate) enum MonoItemCollectionStrategy { Eager, Lazy, } -pub struct UsageMap<'tcx> { +pub(crate) struct UsageMap<'tcx> { // Maps every mono item to the mono items used by it. used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>, @@ -306,13 +306,17 @@ impl<'tcx> UsageMap<'tcx> { assert!(self.used_map.insert(user_item, used_items).is_none()); } - pub fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] { + pub(crate) fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] { self.user_map.get(&item).map(|items| items.as_slice()).unwrap_or(&[]) } /// Internally iterate over all inlined items used by `item`. - pub fn for_each_inlined_used_item<F>(&self, tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>, mut f: F) - where + pub(crate) fn for_each_inlined_used_item<F>( + &self, + tcx: TyCtxt<'tcx>, + item: MonoItem<'tcx>, + mut f: F, + ) where F: FnMut(MonoItem<'tcx>), { let used_items = self.used_map.get(&item).unwrap(); @@ -1615,6 +1619,6 @@ pub(crate) fn collect_crate_mono_items<'tcx>( (mono_items, state.usage_map.into_inner()) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.hooks.should_codegen_locally = should_codegen_locally; } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index c97e07ee3ba..d5fae6e23cb 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -8,7 +8,7 @@ use crate::fluent_generated as fluent; #[derive(Diagnostic)] #[diag(monomorphize_recursion_limit)] -pub struct RecursionLimit { +pub(crate) struct RecursionLimit { #[primary_span] pub span: Span, pub shrunk: String, @@ -22,13 +22,13 @@ pub struct RecursionLimit { #[derive(Diagnostic)] #[diag(monomorphize_no_optimized_mir)] -pub struct NoOptimizedMir { +pub(crate) struct NoOptimizedMir { #[note] pub span: Span, pub crate_name: Symbol, } -pub struct UnusedGenericParamsHint { +pub(crate) struct UnusedGenericParamsHint { pub span: Span, pub param_spans: Vec<Span>, pub param_names: Vec<String>, @@ -53,7 +53,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for UnusedGenericParamsHint { #[derive(LintDiagnostic)] #[diag(monomorphize_large_assignments)] #[note] -pub struct LargeAssignmentsLint { +pub(crate) struct LargeAssignmentsLint { #[label] pub span: Span, pub size: u64, @@ -62,7 +62,7 @@ pub struct LargeAssignmentsLint { #[derive(Diagnostic)] #[diag(monomorphize_symbol_already_defined)] -pub struct SymbolAlreadyDefined { +pub(crate) struct SymbolAlreadyDefined { #[primary_span] pub span: Option<Span>, pub symbol: String, @@ -70,13 +70,13 @@ pub struct SymbolAlreadyDefined { #[derive(Diagnostic)] #[diag(monomorphize_couldnt_dump_mono_stats)] -pub struct CouldntDumpMonoStats { +pub(crate) struct CouldntDumpMonoStats { pub error: String, } #[derive(Diagnostic)] #[diag(monomorphize_encountered_error_while_instantiating)] -pub struct EncounteredErrorWhileInstantiating { +pub(crate) struct EncounteredErrorWhileInstantiating { #[primary_span] pub span: Span, pub formatted_item: String, @@ -85,10 +85,10 @@ pub struct EncounteredErrorWhileInstantiating { #[derive(Diagnostic)] #[diag(monomorphize_start_not_found)] #[help] -pub struct StartNotFound; +pub(crate) struct StartNotFound; #[derive(Diagnostic)] #[diag(monomorphize_unknown_cgu_collection_mode)] -pub struct UnknownCguCollectionMode<'a> { +pub(crate) struct UnknownCguCollectionMode<'a> { pub mode: &'a str, } diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index d6b0f9c4d28..b22e8e30465 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,5 +1,6 @@ // tidy-alphabetical-start #![feature(array_windows)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_hir::lang_items::LangItem; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 2f0088fb34f..0d295b8f280 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1300,7 +1300,7 @@ fn dump_mono_items_stats<'tcx>( Ok(()) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.collect_and_partition_mono_items = collect_and_partition_mono_items; providers.is_codegened_item = |tcx, def_id| { diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index b59c7bcffa9..c65ad9fa67e 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -19,7 +19,7 @@ use tracing::{debug, instrument}; use crate::errors::UnusedGenericParamsHint; /// Provide implementations of queries relating to polymorphization analysis. -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.unused_generic_params = unused_generic_params; } diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index 0a5b4278058..ea244b5107a 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -4,6 +4,10 @@ //! but were uplifted in the process of making the new trait solver generic. //! So if you got to this crate from the old solver, it's totally normal. +// tidy-alphabetical-start +#![warn(unreachable_pub)] +// tidy-alphabetical-end + pub mod canonicalizer; pub mod coherence; pub mod delegate; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index e328284c001..3f2f34d3255 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -92,7 +92,7 @@ where #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] // FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate. -pub struct NestedGoals<I: Interner> { +struct NestedGoals<I: Interner> { /// These normalizes-to goals are treated specially during the evaluation /// loop. In each iteration we take the RHS of the projection, replace it with /// a fresh inference variable, and only after evaluating that goal do we @@ -109,11 +109,11 @@ pub struct NestedGoals<I: Interner> { } impl<I: Interner> NestedGoals<I> { - pub fn new() -> Self { + fn new() -> Self { Self { normalizes_to_goals: Vec::new(), goals: Vec::new() } } - pub fn is_empty(&self) -> bool { + fn is_empty(&self) -> bool { self.normalizes_to_goals.is_empty() && self.goals.is_empty() } } diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index 86fb036cd3d..742d45de7d3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -222,13 +222,13 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { self.state.as_deref_mut() } - pub fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> { + pub(crate) fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> { let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData }; nested.enter_probe(); nested } - pub fn finalize(self) -> Option<inspect::GoalEvaluation<I>> { + pub(crate) fn finalize(self) -> Option<inspect::GoalEvaluation<I>> { match *self.state? { DebugSolver::GoalEvaluation(wip_goal_evaluation) => { Some(wip_goal_evaluation.finalize()) @@ -237,22 +237,22 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> { + pub(crate) fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> { match generate_proof_tree { GenerateProofTree::No => ProofTreeBuilder::new_noop(), GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } - pub fn new_root() -> ProofTreeBuilder<D> { + fn new_root() -> ProofTreeBuilder<D> { ProofTreeBuilder::new(DebugSolver::Root) } - pub fn new_noop() -> ProofTreeBuilder<D> { + fn new_noop() -> ProofTreeBuilder<D> { ProofTreeBuilder { state: None, _infcx: PhantomData } } - pub fn is_noop(&self) -> bool { + pub(crate) fn is_noop(&self) -> bool { self.state.is_none() } @@ -272,7 +272,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { }) } - pub fn new_canonical_goal_evaluation( + pub(crate) fn new_canonical_goal_evaluation( &mut self, goal: CanonicalInput<I>, ) -> ProofTreeBuilder<D> { @@ -284,7 +284,10 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { }) } - pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<D>) { + pub(crate) fn canonical_goal_evaluation( + &mut self, + canonical_goal_evaluation: ProofTreeBuilder<D>, + ) { if let Some(this) = self.as_mut() { match (this, *canonical_goal_evaluation.state.unwrap()) { ( @@ -299,7 +302,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn canonical_goal_evaluation_overflow(&mut self) { + pub(crate) fn canonical_goal_evaluation_overflow(&mut self) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -310,7 +313,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) { + pub(crate) fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) { if let Some(this) = self.as_mut() { match this { DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), @@ -322,7 +325,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn new_goal_evaluation_step( + pub(crate) fn new_goal_evaluation_step( &mut self, var_values: ty::CanonicalVarValues<I>, instantiated_goal: QueryInput<I, I::Predicate>, @@ -340,7 +343,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { }) } - pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) { + pub(crate) fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) { if let Some(this) = self.as_mut() { match (this, *goal_evaluation_step.state.unwrap()) { ( @@ -354,7 +357,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) { + pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -364,7 +367,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn enter_probe(&mut self) { + fn enter_probe(&mut self) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -381,7 +384,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) { + pub(crate) fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -392,7 +395,11 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn probe_final_state(&mut self, delegate: &D, max_input_universe: ty::UniverseIndex) { + pub(crate) fn probe_final_state( + &mut self, + delegate: &D, + max_input_universe: ty::UniverseIndex, + ) { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -409,7 +416,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn add_normalizes_to_goal( + pub(crate) fn add_normalizes_to_goal( &mut self, delegate: &D, max_input_universe: ty::UniverseIndex, @@ -423,7 +430,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { ); } - pub fn add_goal( + pub(crate) fn add_goal( &mut self, delegate: &D, max_input_universe: ty::UniverseIndex, @@ -469,7 +476,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) { + pub(crate) fn make_canonical_response(&mut self, shallow_certainty: Certainty) { match self.as_mut() { Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state @@ -482,7 +489,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { } } - pub fn finish_probe(mut self) -> ProofTreeBuilder<D> { + pub(crate) fn finish_probe(mut self) -> ProofTreeBuilder<D> { match self.as_mut() { None => {} Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { @@ -497,7 +504,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { self } - pub fn query_result(&mut self, result: QueryResult<I>) { + pub(crate) fn query_result(&mut self, result: QueryResult<I>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 5738173c7a8..c7a9846cd97 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -862,7 +862,7 @@ where _ecx: &mut EvalCtxt<'_, D>, goal: Goal<I, Self>, ) -> Result<Candidate<I>, NoSolution> { - panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal) + panic!("`TransmuteFrom` does not have an associated type: {:?}", goal) } fn consider_builtin_effects_intersection_candidate( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 120f96d24bd..6a0703c5313 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -97,7 +97,7 @@ where /// Checks whether each generic argument is simply a unique generic placeholder. /// /// FIXME: Interner argument is needed to constrain the `I` parameter. -pub fn uses_unique_placeholders_ignoring_regions<I: Interner>( +fn uses_unique_placeholders_ignoring_regions<I: Interner>( _cx: I, args: I::GenericArgs, ) -> Result<(), NotUniqueParam<I>> { @@ -130,7 +130,7 @@ pub fn uses_unique_placeholders_ignoring_regions<I: Interner>( } // FIXME: This should check for dupes and non-params first, then infer vars. -pub enum NotUniqueParam<I: Interner> { +enum NotUniqueParam<I: Interner> { DuplicateParam(I::GenericArg), NotParam(I::GenericArg), } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index abaff7d9c19..da1103a4fe5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -260,7 +260,7 @@ pub(crate) struct NotAsNegationOperator { } #[derive(Subdiagnostic)] -pub enum NotAsNegationOperatorSub { +pub(crate) enum NotAsNegationOperatorSub { #[suggestion( parse_unexpected_token_after_not_default, style = "verbose", @@ -424,7 +424,7 @@ pub(crate) enum IfExpressionMissingThenBlockSub { #[derive(Diagnostic)] #[diag(parse_ternary_operator)] #[help] -pub struct TernaryOperator { +pub(crate) struct TernaryOperator { #[primary_span] pub span: Span, } @@ -1088,7 +1088,7 @@ pub(crate) enum ExpectedIdentifierFound { } impl ExpectedIdentifierFound { - pub fn new(token_descr: Option<TokenDescription>, span: Span) -> Self { + pub(crate) fn new(token_descr: Option<TokenDescription>, span: Span) -> Self { (match token_descr { Some(TokenDescription::ReservedIdentifier) => { ExpectedIdentifierFound::ReservedIdentifier @@ -1659,7 +1659,7 @@ pub(crate) struct SelfArgumentPointer { #[derive(Diagnostic)] #[diag(parse_unexpected_token_after_dot)] -pub struct UnexpectedTokenAfterDot<'a> { +pub(crate) struct UnexpectedTokenAfterDot<'a> { #[primary_span] pub span: Span, pub actual: Cow<'a, str>, @@ -1928,7 +1928,7 @@ pub(crate) enum UnexpectedTokenAfterStructName { } impl UnexpectedTokenAfterStructName { - pub fn new(span: Span, token: Token) -> Self { + pub(crate) fn new(span: Span, token: Token) -> Self { match TokenDescription::from_token(&token) { Some(TokenDescription::ReservedIdentifier) => Self::ReservedIdentifier { span, token }, Some(TokenDescription::Keyword) => Self::Keyword { span, token }, @@ -2006,7 +2006,7 @@ pub(crate) enum TopLevelOrPatternNotAllowed { #[derive(Diagnostic)] #[diag(parse_cannot_be_raw_ident)] -pub struct CannotBeRawIdent { +pub(crate) struct CannotBeRawIdent { #[primary_span] pub span: Span, pub ident: Symbol, @@ -2014,14 +2014,14 @@ pub struct CannotBeRawIdent { #[derive(Diagnostic)] #[diag(parse_keyword_lifetime)] -pub struct KeywordLifetime { +pub(crate) struct KeywordLifetime { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(parse_invalid_label)] -pub struct InvalidLabel { +pub(crate) struct InvalidLabel { #[primary_span] pub span: Span, pub name: Symbol, @@ -2029,7 +2029,7 @@ pub struct InvalidLabel { #[derive(Diagnostic)] #[diag(parse_cr_doc_comment)] -pub struct CrDocComment { +pub(crate) struct CrDocComment { #[primary_span] pub span: Span, pub block: bool, @@ -2037,14 +2037,14 @@ pub struct CrDocComment { #[derive(Diagnostic)] #[diag(parse_no_digits_literal, code = E0768)] -pub struct NoDigitsLiteral { +pub(crate) struct NoDigitsLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(parse_invalid_digit_literal)] -pub struct InvalidDigitLiteral { +pub(crate) struct InvalidDigitLiteral { #[primary_span] pub span: Span, pub base: u32, @@ -2052,14 +2052,14 @@ pub struct InvalidDigitLiteral { #[derive(Diagnostic)] #[diag(parse_empty_exponent_float)] -pub struct EmptyExponentFloat { +pub(crate) struct EmptyExponentFloat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(parse_float_literal_unsupported_base)] -pub struct FloatLiteralUnsupportedBase { +pub(crate) struct FloatLiteralUnsupportedBase { #[primary_span] pub span: Span, pub base: &'static str, @@ -2068,7 +2068,7 @@ pub struct FloatLiteralUnsupportedBase { #[derive(Diagnostic)] #[diag(parse_unknown_prefix)] #[note] -pub struct UnknownPrefix<'a> { +pub(crate) struct UnknownPrefix<'a> { #[primary_span] #[label] pub span: Span, @@ -2079,12 +2079,12 @@ pub struct UnknownPrefix<'a> { #[derive(Subdiagnostic)] #[note(parse_macro_expands_to_adt_field)] -pub struct MacroExpandsToAdtField<'a> { +pub(crate) struct MacroExpandsToAdtField<'a> { pub adt_ty: &'a str, } #[derive(Subdiagnostic)] -pub enum UnknownPrefixSugg { +pub(crate) enum UnknownPrefixSugg { #[suggestion( parse_suggestion_br, code = "br", @@ -2114,7 +2114,7 @@ pub enum UnknownPrefixSugg { #[derive(Diagnostic)] #[diag(parse_too_many_hashes)] -pub struct TooManyHashes { +pub(crate) struct TooManyHashes { #[primary_span] pub span: Span, pub num: u32, @@ -2122,7 +2122,7 @@ pub struct TooManyHashes { #[derive(Diagnostic)] #[diag(parse_unknown_start_of_token)] -pub struct UnknownTokenStart { +pub(crate) struct UnknownTokenStart { #[primary_span] pub span: Span, pub escaped: String, @@ -2135,7 +2135,7 @@ pub struct UnknownTokenStart { } #[derive(Subdiagnostic)] -pub enum TokenSubstitution { +pub(crate) enum TokenSubstitution { #[suggestion( parse_sugg_quotes, code = "{suggestion}", @@ -2168,16 +2168,16 @@ pub enum TokenSubstitution { #[derive(Subdiagnostic)] #[note(parse_note_repeats)] -pub struct UnknownTokenRepeat { +pub(crate) struct UnknownTokenRepeat { pub repeats: usize, } #[derive(Subdiagnostic)] #[help(parse_help_null)] -pub struct UnknownTokenNull; +pub(crate) struct UnknownTokenNull; #[derive(Diagnostic)] -pub enum UnescapeError { +pub(crate) enum UnescapeError { #[diag(parse_invalid_unicode_escape)] #[help] InvalidUnicodeEscape { @@ -2322,7 +2322,7 @@ pub enum UnescapeError { } #[derive(Subdiagnostic)] -pub enum MoreThanOneCharSugg { +pub(crate) enum MoreThanOneCharSugg { #[suggestion( parse_consider_normalized, code = "{normalized}", @@ -2370,7 +2370,7 @@ pub enum MoreThanOneCharSugg { } #[derive(Subdiagnostic)] -pub enum MoreThanOneCharNote { +pub(crate) enum MoreThanOneCharNote { #[note(parse_followed_by)] AllCombining { #[primary_span] @@ -2388,7 +2388,7 @@ pub enum MoreThanOneCharNote { } #[derive(Subdiagnostic)] -pub enum NoBraceUnicodeSub { +pub(crate) enum NoBraceUnicodeSub { #[suggestion( parse_use_braces, code = "{suggestion}", @@ -2703,7 +2703,7 @@ pub(crate) struct InvalidDynKeyword { } #[derive(Subdiagnostic)] -pub enum HelpUseLatestEdition { +pub(crate) enum HelpUseLatestEdition { #[help(parse_help_set_edition_cargo)] #[note(parse_note_edition_guide)] Cargo { edition: Edition }, @@ -2713,7 +2713,7 @@ pub enum HelpUseLatestEdition { } impl HelpUseLatestEdition { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let edition = LATEST_STABLE_EDITION; if rustc_session::utils::was_invoked_from_cargo() { Self::Cargo { edition } @@ -2725,7 +2725,7 @@ impl HelpUseLatestEdition { #[derive(Diagnostic)] #[diag(parse_box_syntax_removed)] -pub struct BoxSyntaxRemoved { +pub(crate) struct BoxSyntaxRemoved { #[primary_span] pub span: Span, #[subdiagnostic] @@ -2738,7 +2738,7 @@ pub struct BoxSyntaxRemoved { applicability = "machine-applicable", style = "verbose" )] -pub struct AddBoxNew { +pub(crate) struct AddBoxNew { #[suggestion_part(code = "Box::new(")] pub box_kw_and_lo: Span, #[suggestion_part(code = ")")] @@ -3190,7 +3190,7 @@ pub(crate) struct DotDotRangeAttribute { #[derive(Diagnostic)] #[diag(parse_invalid_attr_unsafe)] #[note] -pub struct InvalidAttrUnsafe { +pub(crate) struct InvalidAttrUnsafe { #[primary_span] #[label] pub span: Span, @@ -3199,7 +3199,7 @@ pub struct InvalidAttrUnsafe { #[derive(Diagnostic)] #[diag(parse_unsafe_attr_outside_unsafe)] -pub struct UnsafeAttrOutsideUnsafe { +pub(crate) struct UnsafeAttrOutsideUnsafe { #[primary_span] #[label] pub span: Span, @@ -3212,7 +3212,7 @@ pub struct UnsafeAttrOutsideUnsafe { parse_unsafe_attr_outside_unsafe_suggestion, applicability = "machine-applicable" )] -pub struct UnsafeAttrOutsideUnsafeSuggestion { +pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, #[suggestion_part(code = ")")] @@ -3221,7 +3221,7 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion { #[derive(Diagnostic)] #[diag(parse_binder_before_modifiers)] -pub struct BinderBeforeModifiers { +pub(crate) struct BinderBeforeModifiers { #[primary_span] pub binder_span: Span, #[label] @@ -3230,7 +3230,7 @@ pub struct BinderBeforeModifiers { #[derive(Diagnostic)] #[diag(parse_binder_and_polarity)] -pub struct BinderAndPolarity { +pub(crate) struct BinderAndPolarity { #[primary_span] pub polarity_span: Span, #[label] @@ -3240,7 +3240,7 @@ pub struct BinderAndPolarity { #[derive(Diagnostic)] #[diag(parse_modifiers_and_polarity)] -pub struct PolarityAndModifiers { +pub(crate) struct PolarityAndModifiers { #[primary_span] pub polarity_span: Span, #[label] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 37079271493..788bb732ef7 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -11,6 +11,7 @@ #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::path::Path; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 14da6c331f1..c6a5e1908f7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -51,7 +51,9 @@ impl<'a> Parser<'a> { } /// Parses the contents of a module (inner attributes followed by module items). - /// We exit once we hit `term` + /// We exit once we hit `term` which can be either + /// - EOF (for files) + /// - `}` for mod items pub fn parse_mod( &mut self, term: &TokenKind, diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 999f6f0eeb0..e66d0df012b 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -86,25 +86,7 @@ impl<'a> Parser<'a> { token::Interpolated(nt) => may_be_ident(nt), _ => false, }, - NonterminalKind::Pat(pat_kind) => match &token.kind { - // box, ref, mut, and other identifiers (can stricten) - token::Ident(..) | token::NtIdent(..) | - token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern - token::OpenDelim(Delimiter::Bracket) | // slice pattern - token::BinOp(token::And) | // reference - token::BinOp(token::Minus) | // negative literal - token::AndAnd | // double reference - token::Literal(_) | // literal - token::DotDot | // range pattern (future compat) - token::DotDotDot | // range pattern (future compat) - token::PathSep | // path - token::Lt | // path (UFCS constant) - token::BinOp(token::Shl) => true, // path (double UFCS) - // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(pat_kind, PatWithOr), - token::Interpolated(nt) => may_be_ident(nt), - _ => false, - }, + NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind), NonterminalKind::Lifetime => match &token.kind { token::Lifetime(_) | token::NtLifetime(..) => true, _ => false, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index cc68ae237ba..8233f9a7943 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -444,7 +444,11 @@ impl<'a> Parser<'a> { let mut lo = self.token.span; - if self.token.is_keyword(kw::Let) && self.look_ahead(1, |tok| tok.can_begin_pattern()) { + if self.token.is_keyword(kw::Let) + && self.look_ahead(1, |tok| { + tok.can_begin_pattern(token::NtPatKind::PatParam { inferred: false }) + }) + { self.bump(); self.dcx().emit_err(RemoveLet { span: lo }); lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index d8bf10e6021..8ee40ecd77e 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -378,7 +378,10 @@ impl<'a> Parser<'a> { if self.may_recover() && prev_token_before_parsing == token::PathSep && (style == PathStyle::Expr && self.token.can_begin_expr() - || style == PathStyle::Pat && self.token.can_begin_pattern()) + || style == PathStyle::Pat + && self.token.can_begin_pattern(token::NtPatKind::PatParam { + inferred: false, + })) { snapshot = Some(self.create_snapshot_for_diagnostic()); } diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index cb758150789..51084ef4441 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -13,6 +13,7 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::{iter, str, string}; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e7f208d5ad5..38450fc288a 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -672,6 +672,10 @@ passes_should_be_applied_to_fn = *[false] not a function definition } +passes_should_be_applied_to_fn_or_unit_struct = + attribute should be applied to a function definition or unit struct + .label = not a function definition or a unit struct + passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d1dac9ca6da..5dbb3854c8f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -517,6 +517,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::no_mangle, sym::naked, sym::instruction_set, + sym::repr, // code generation sym::cold, sym::target_feature, @@ -746,12 +747,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); } + Target::Struct if self.tcx.features().struct_target_features => { + let ty = self.tcx.hir_node(hir_id).expect_item(); + match ty.kind { + ItemKind::Struct(data, _) => { + if data.fields().len() != 0 { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } + } + _ => { + panic!("Target::Struct for a non-struct"); + } + } + } _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); + if self.tcx.features().struct_target_features { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { + attr_span: attr.span, + defn_span: span, + }); + } else { + self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); + } } } } diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 5d871bacb1d..fec149c8c43 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -95,6 +95,6 @@ fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualize visitor.visualizers } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.debugger_visualizers = debugger_visualizers; } diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 624ebb2f9f2..425e203f2b0 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -90,7 +90,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems { items } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.diagnostic_items = diagnostic_items; providers.all_diagnostic_items = all_diagnostic_items; } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1202351bdcd..1e9ab7af9be 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -18,41 +18,41 @@ use crate::lang_items::Duplicate; #[derive(LintDiagnostic)] #[diag(passes_incorrect_do_not_recommend_location)] -pub struct IncorrectDoNotRecommendLocation; +pub(crate) struct IncorrectDoNotRecommendLocation; #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] -pub struct OuterCrateLevelAttr; +pub(crate) struct OuterCrateLevelAttr; #[derive(LintDiagnostic)] #[diag(passes_inner_crate_level_attr)] -pub struct InnerCrateLevelAttr; +pub(crate) struct InnerCrateLevelAttr; #[derive(LintDiagnostic)] #[diag(passes_ignored_attr_with_macro)] -pub struct IgnoredAttrWithMacro<'a> { +pub(crate) struct IgnoredAttrWithMacro<'a> { pub sym: &'a str, } #[derive(LintDiagnostic)] #[diag(passes_ignored_attr)] -pub struct IgnoredAttr<'a> { +pub(crate) struct IgnoredAttr<'a> { pub sym: &'a str, } #[derive(LintDiagnostic)] #[diag(passes_inline_ignored_function_prototype)] -pub struct IgnoredInlineAttrFnProto; +pub(crate) struct IgnoredInlineAttrFnProto; #[derive(LintDiagnostic)] #[diag(passes_inline_ignored_constants)] #[warning] #[note] -pub struct IgnoredInlineAttrConstants; +pub(crate) struct IgnoredInlineAttrConstants; #[derive(Diagnostic)] #[diag(passes_inline_not_fn_or_closure, code = E0518)] -pub struct InlineNotFnOrClosure { +pub(crate) struct InlineNotFnOrClosure { #[primary_span] pub attr_span: Span, #[label] @@ -61,7 +61,7 @@ pub struct InlineNotFnOrClosure { #[derive(Diagnostic)] #[diag(passes_coverage_not_fn_or_closure, code = E0788)] -pub struct CoverageNotFnOrClosure { +pub(crate) struct CoverageNotFnOrClosure { #[primary_span] pub attr_span: Span, #[label] @@ -70,11 +70,11 @@ pub struct CoverageNotFnOrClosure { #[derive(LintDiagnostic)] #[diag(passes_optimize_not_fn_or_closure)] -pub struct OptimizeNotFnOrClosure; +pub(crate) struct OptimizeNotFnOrClosure; #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn)] -pub struct AttrShouldBeAppliedToFn { +pub(crate) struct AttrShouldBeAppliedToFn { #[primary_span] pub attr_span: Span, #[label] @@ -83,8 +83,17 @@ pub struct AttrShouldBeAppliedToFn { } #[derive(Diagnostic)] +#[diag(passes_should_be_applied_to_fn_or_unit_struct)] +pub(crate) struct AttrShouldBeAppliedToFnOrUnitStruct { + #[primary_span] + pub attr_span: Span, + #[label] + pub defn_span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] -pub struct TrackedCallerWrongLocation { +pub(crate) struct TrackedCallerWrongLocation { #[primary_span] pub attr_span: Span, #[label] @@ -94,7 +103,7 @@ pub struct TrackedCallerWrongLocation { #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_struct_enum, code = E0701)] -pub struct NonExhaustiveWrongLocation { +pub(crate) struct NonExhaustiveWrongLocation { #[primary_span] pub attr_span: Span, #[label] @@ -103,7 +112,7 @@ pub struct NonExhaustiveWrongLocation { #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_trait)] -pub struct AttrShouldBeAppliedToTrait { +pub(crate) struct AttrShouldBeAppliedToTrait { #[primary_span] pub attr_span: Span, #[label] @@ -112,11 +121,11 @@ pub struct AttrShouldBeAppliedToTrait { #[derive(LintDiagnostic)] #[diag(passes_target_feature_on_statement)] -pub struct TargetFeatureOnStatement; +pub(crate) struct TargetFeatureOnStatement; #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_static)] -pub struct AttrShouldBeAppliedToStatic { +pub(crate) struct AttrShouldBeAppliedToStatic { #[primary_span] pub attr_span: Span, #[label] @@ -125,7 +134,7 @@ pub struct AttrShouldBeAppliedToStatic { #[derive(Diagnostic)] #[diag(passes_doc_expect_str)] -pub struct DocExpectStr<'a> { +pub(crate) struct DocExpectStr<'a> { #[primary_span] pub attr_span: Span, pub attr_name: &'a str, @@ -133,7 +142,7 @@ pub struct DocExpectStr<'a> { #[derive(Diagnostic)] #[diag(passes_doc_alias_empty)] -pub struct DocAliasEmpty<'a> { +pub(crate) struct DocAliasEmpty<'a> { #[primary_span] pub span: Span, pub attr_str: &'a str, @@ -141,7 +150,7 @@ pub struct DocAliasEmpty<'a> { #[derive(Diagnostic)] #[diag(passes_doc_alias_bad_char)] -pub struct DocAliasBadChar<'a> { +pub(crate) struct DocAliasBadChar<'a> { #[primary_span] pub span: Span, pub attr_str: &'a str, @@ -150,7 +159,7 @@ pub struct DocAliasBadChar<'a> { #[derive(Diagnostic)] #[diag(passes_doc_alias_start_end)] -pub struct DocAliasStartEnd<'a> { +pub(crate) struct DocAliasStartEnd<'a> { #[primary_span] pub span: Span, pub attr_str: &'a str, @@ -158,7 +167,7 @@ pub struct DocAliasStartEnd<'a> { #[derive(Diagnostic)] #[diag(passes_doc_alias_bad_location)] -pub struct DocAliasBadLocation<'a> { +pub(crate) struct DocAliasBadLocation<'a> { #[primary_span] pub span: Span, pub attr_str: &'a str, @@ -167,7 +176,7 @@ pub struct DocAliasBadLocation<'a> { #[derive(Diagnostic)] #[diag(passes_doc_alias_not_an_alias)] -pub struct DocAliasNotAnAlias<'a> { +pub(crate) struct DocAliasNotAnAlias<'a> { #[primary_span] pub span: Span, pub attr_str: &'a str, @@ -175,42 +184,42 @@ pub struct DocAliasNotAnAlias<'a> { #[derive(LintDiagnostic)] #[diag(passes_doc_alias_duplicated)] -pub struct DocAliasDuplicated { +pub(crate) struct DocAliasDuplicated { #[label] pub first_defn: Span, } #[derive(Diagnostic)] #[diag(passes_doc_alias_not_string_literal)] -pub struct DocAliasNotStringLiteral { +pub(crate) struct DocAliasNotStringLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_doc_alias_malformed)] -pub struct DocAliasMalformed { +pub(crate) struct DocAliasMalformed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_doc_keyword_empty_mod)] -pub struct DocKeywordEmptyMod { +pub(crate) struct DocKeywordEmptyMod { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_doc_keyword_not_mod)] -pub struct DocKeywordNotMod { +pub(crate) struct DocKeywordNotMod { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_doc_keyword_invalid_ident)] -pub struct DocKeywordInvalidIdent { +pub(crate) struct DocKeywordInvalidIdent { #[primary_span] pub span: Span, pub doc_keyword: Symbol, @@ -218,14 +227,14 @@ pub struct DocKeywordInvalidIdent { #[derive(Diagnostic)] #[diag(passes_doc_fake_variadic_not_valid)] -pub struct DocFakeVariadicNotValid { +pub(crate) struct DocFakeVariadicNotValid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_doc_keyword_only_impl)] -pub struct DocKeywordOnlyImpl { +pub(crate) struct DocKeywordOnlyImpl { #[primary_span] pub span: Span, } @@ -233,7 +242,7 @@ pub struct DocKeywordOnlyImpl { #[derive(Diagnostic)] #[diag(passes_doc_inline_conflict)] #[help] -pub struct DocKeywordConflict { +pub(crate) struct DocKeywordConflict { #[primary_span] pub spans: MultiSpan, } @@ -241,7 +250,7 @@ pub struct DocKeywordConflict { #[derive(LintDiagnostic)] #[diag(passes_doc_inline_only_use)] #[note] -pub struct DocInlineOnlyUse { +pub(crate) struct DocInlineOnlyUse { #[label] pub attr_span: Span, #[label(passes_not_a_use_item_label)] @@ -251,7 +260,7 @@ pub struct DocInlineOnlyUse { #[derive(LintDiagnostic)] #[diag(passes_doc_masked_only_extern_crate)] #[note] -pub struct DocMaskedOnlyExternCrate { +pub(crate) struct DocMaskedOnlyExternCrate { #[label] pub attr_span: Span, #[label(passes_not_an_extern_crate_label)] @@ -260,7 +269,7 @@ pub struct DocMaskedOnlyExternCrate { #[derive(LintDiagnostic)] #[diag(passes_doc_masked_not_extern_crate_self)] -pub struct DocMaskedNotExternCrateSelf { +pub(crate) struct DocMaskedNotExternCrateSelf { #[label] pub attr_span: Span, #[label(passes_extern_crate_self_label)] @@ -269,7 +278,7 @@ pub struct DocMaskedNotExternCrateSelf { #[derive(Diagnostic)] #[diag(passes_doc_attr_not_crate_level)] -pub struct DocAttrNotCrateLevel<'a> { +pub(crate) struct DocAttrNotCrateLevel<'a> { #[primary_span] pub span: Span, pub attr_name: &'a str, @@ -277,25 +286,25 @@ pub struct DocAttrNotCrateLevel<'a> { #[derive(LintDiagnostic)] #[diag(passes_doc_test_unknown)] -pub struct DocTestUnknown { +pub(crate) struct DocTestUnknown { pub path: String, } #[derive(LintDiagnostic)] #[diag(passes_doc_test_literal)] -pub struct DocTestLiteral; +pub(crate) struct DocTestLiteral; #[derive(LintDiagnostic)] #[diag(passes_doc_test_takes_list)] -pub struct DocTestTakesList; +pub(crate) struct DocTestTakesList; #[derive(LintDiagnostic)] #[diag(passes_doc_cfg_hide_takes_list)] -pub struct DocCfgHideTakesList; +pub(crate) struct DocCfgHideTakesList; #[derive(LintDiagnostic)] #[diag(passes_doc_test_unknown_any)] -pub struct DocTestUnknownAny { +pub(crate) struct DocTestUnknownAny { pub path: String, } @@ -303,7 +312,7 @@ pub struct DocTestUnknownAny { #[diag(passes_doc_test_unknown_spotlight)] #[note] #[note(passes_no_op_note)] -pub struct DocTestUnknownSpotlight { +pub(crate) struct DocTestUnknownSpotlight { pub path: String, #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")] pub span: Span, @@ -311,7 +320,7 @@ pub struct DocTestUnknownSpotlight { #[derive(LintDiagnostic)] #[diag(passes_doc_test_unknown_include)] -pub struct DocTestUnknownInclude { +pub(crate) struct DocTestUnknownInclude { pub path: String, pub value: String, pub inner: &'static str, @@ -321,11 +330,11 @@ pub struct DocTestUnknownInclude { #[derive(LintDiagnostic)] #[diag(passes_doc_invalid)] -pub struct DocInvalid; +pub(crate) struct DocInvalid; #[derive(Diagnostic)] #[diag(passes_pass_by_value)] -pub struct PassByValue { +pub(crate) struct PassByValue { #[primary_span] pub attr_span: Span, #[label] @@ -334,7 +343,7 @@ pub struct PassByValue { #[derive(Diagnostic)] #[diag(passes_allow_incoherent_impl)] -pub struct AllowIncoherentImpl { +pub(crate) struct AllowIncoherentImpl { #[primary_span] pub attr_span: Span, #[label] @@ -343,7 +352,7 @@ pub struct AllowIncoherentImpl { #[derive(Diagnostic)] #[diag(passes_has_incoherent_inherent_impl)] -pub struct HasIncoherentInherentImpl { +pub(crate) struct HasIncoherentInherentImpl { #[primary_span] pub attr_span: Span, #[label] @@ -352,35 +361,35 @@ pub struct HasIncoherentInherentImpl { #[derive(Diagnostic)] #[diag(passes_both_ffi_const_and_pure, code = E0757)] -pub struct BothFfiConstAndPure { +pub(crate) struct BothFfiConstAndPure { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] #[diag(passes_ffi_pure_invalid_target, code = E0755)] -pub struct FfiPureInvalidTarget { +pub(crate) struct FfiPureInvalidTarget { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] #[diag(passes_ffi_const_invalid_target, code = E0756)] -pub struct FfiConstInvalidTarget { +pub(crate) struct FfiConstInvalidTarget { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] #[diag(passes_must_use_no_effect)] -pub struct MustUseNoEffect { +pub(crate) struct MustUseNoEffect { pub article: &'static str, pub target: rustc_hir::Target, } #[derive(Diagnostic)] #[diag(passes_must_not_suspend)] -pub struct MustNotSuspend { +pub(crate) struct MustNotSuspend { #[primary_span] pub attr_span: Span, #[label] @@ -390,7 +399,7 @@ pub struct MustNotSuspend { #[derive(LintDiagnostic)] #[diag(passes_cold)] #[warning] -pub struct Cold { +pub(crate) struct Cold { #[label] pub span: Span, pub on_crate: bool, @@ -399,7 +408,7 @@ pub struct Cold { #[derive(LintDiagnostic)] #[diag(passes_link)] #[warning] -pub struct Link { +pub(crate) struct Link { #[label] pub span: Option<Span>, } @@ -407,7 +416,7 @@ pub struct Link { #[derive(LintDiagnostic)] #[diag(passes_link_name)] #[warning] -pub struct LinkName<'a> { +pub(crate) struct LinkName<'a> { #[help] pub attr_span: Option<Span>, #[label] @@ -417,7 +426,7 @@ pub struct LinkName<'a> { #[derive(Diagnostic)] #[diag(passes_no_link)] -pub struct NoLink { +pub(crate) struct NoLink { #[primary_span] pub attr_span: Span, #[label] @@ -426,7 +435,7 @@ pub struct NoLink { #[derive(Diagnostic)] #[diag(passes_export_name)] -pub struct ExportName { +pub(crate) struct ExportName { #[primary_span] pub attr_span: Span, #[label] @@ -435,7 +444,7 @@ pub struct ExportName { #[derive(Diagnostic)] #[diag(passes_rustc_layout_scalar_valid_range_not_struct)] -pub struct RustcLayoutScalarValidRangeNotStruct { +pub(crate) struct RustcLayoutScalarValidRangeNotStruct { #[primary_span] pub attr_span: Span, #[label] @@ -444,14 +453,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct { #[derive(Diagnostic)] #[diag(passes_rustc_layout_scalar_valid_range_arg)] -pub struct RustcLayoutScalarValidRangeArg { +pub(crate) struct RustcLayoutScalarValidRangeArg { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_only)] -pub struct RustcLegacyConstGenericsOnly { +pub(crate) struct RustcLegacyConstGenericsOnly { #[primary_span] pub attr_span: Span, #[label] @@ -460,7 +469,7 @@ pub struct RustcLegacyConstGenericsOnly { #[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_index)] -pub struct RustcLegacyConstGenericsIndex { +pub(crate) struct RustcLegacyConstGenericsIndex { #[primary_span] pub attr_span: Span, #[label] @@ -469,7 +478,7 @@ pub struct RustcLegacyConstGenericsIndex { #[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_index_exceed)] -pub struct RustcLegacyConstGenericsIndexExceed { +pub(crate) struct RustcLegacyConstGenericsIndexExceed { #[primary_span] #[label] pub span: Span, @@ -478,14 +487,14 @@ pub struct RustcLegacyConstGenericsIndexExceed { #[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_index_negative)] -pub struct RustcLegacyConstGenericsIndexNegative { +pub(crate) struct RustcLegacyConstGenericsIndexNegative { #[primary_span] pub invalid_args: Vec<Span>, } #[derive(Diagnostic)] #[diag(passes_rustc_dirty_clean)] -pub struct RustcDirtyClean { +pub(crate) struct RustcDirtyClean { #[primary_span] pub span: Span, } @@ -493,7 +502,7 @@ pub struct RustcDirtyClean { #[derive(LintDiagnostic)] #[diag(passes_link_section)] #[warning] -pub struct LinkSection { +pub(crate) struct LinkSection { #[label] pub span: Span, } @@ -502,7 +511,7 @@ pub struct LinkSection { #[diag(passes_no_mangle_foreign)] #[warning] #[note] -pub struct NoMangleForeign { +pub(crate) struct NoMangleForeign { #[label] pub span: Span, #[suggestion(code = "", applicability = "machine-applicable")] @@ -513,32 +522,32 @@ pub struct NoMangleForeign { #[derive(LintDiagnostic)] #[diag(passes_no_mangle)] #[warning] -pub struct NoMangle { +pub(crate) struct NoMangle { #[label] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_repr_ident, code = E0565)] -pub struct ReprIdent { +pub(crate) struct ReprIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_repr_conflicting, code = E0566)] -pub struct ReprConflicting { +pub(crate) struct ReprConflicting { #[primary_span] pub hint_spans: Vec<Span>, } #[derive(LintDiagnostic)] #[diag(passes_repr_conflicting, code = E0566)] -pub struct ReprConflictingLint; +pub(crate) struct ReprConflictingLint; #[derive(Diagnostic)] #[diag(passes_used_static)] -pub struct UsedStatic { +pub(crate) struct UsedStatic { #[primary_span] pub attr_span: Span, #[label] @@ -548,14 +557,14 @@ pub struct UsedStatic { #[derive(Diagnostic)] #[diag(passes_used_compiler_linker)] -pub struct UsedCompilerLinker { +pub(crate) struct UsedCompilerLinker { #[primary_span] pub spans: Vec<Span>, } #[derive(Diagnostic)] #[diag(passes_allow_internal_unstable)] -pub struct AllowInternalUnstable { +pub(crate) struct AllowInternalUnstable { #[primary_span] pub attr_span: Span, #[label] @@ -564,7 +573,7 @@ pub struct AllowInternalUnstable { #[derive(Diagnostic)] #[diag(passes_debug_visualizer_placement)] -pub struct DebugVisualizerPlacement { +pub(crate) struct DebugVisualizerPlacement { #[primary_span] pub span: Span, } @@ -574,14 +583,14 @@ pub struct DebugVisualizerPlacement { #[note(passes_note_1)] #[note(passes_note_2)] #[note(passes_note_3)] -pub struct DebugVisualizerInvalid { +pub(crate) struct DebugVisualizerInvalid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_debug_visualizer_unreadable)] -pub struct DebugVisualizerUnreadable<'a> { +pub(crate) struct DebugVisualizerUnreadable<'a> { #[primary_span] pub span: Span, pub file: &'a Path, @@ -590,7 +599,7 @@ pub struct DebugVisualizerUnreadable<'a> { #[derive(Diagnostic)] #[diag(passes_rustc_allow_const_fn_unstable)] -pub struct RustcAllowConstFnUnstable { +pub(crate) struct RustcAllowConstFnUnstable { #[primary_span] pub attr_span: Span, #[label] @@ -599,7 +608,7 @@ pub struct RustcAllowConstFnUnstable { #[derive(Diagnostic)] #[diag(passes_rustc_safe_intrinsic)] -pub struct RustcSafeIntrinsic { +pub(crate) struct RustcSafeIntrinsic { #[primary_span] pub attr_span: Span, #[label] @@ -608,7 +617,7 @@ pub struct RustcSafeIntrinsic { #[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] -pub struct RustcStdInternalSymbol { +pub(crate) struct RustcStdInternalSymbol { #[primary_span] pub attr_span: Span, #[label] @@ -617,7 +626,7 @@ pub struct RustcStdInternalSymbol { #[derive(Diagnostic)] #[diag(passes_rustc_pub_transparent)] -pub struct RustcPubTransparent { +pub(crate) struct RustcPubTransparent { #[primary_span] pub attr_span: Span, #[label] @@ -626,28 +635,28 @@ pub struct RustcPubTransparent { #[derive(Diagnostic)] #[diag(passes_link_ordinal)] -pub struct LinkOrdinal { +pub(crate) struct LinkOrdinal { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] #[diag(passes_confusables)] -pub struct Confusables { +pub(crate) struct Confusables { #[primary_span] pub attr_span: Span, } #[derive(Diagnostic)] #[diag(passes_coroutine_on_non_closure)] -pub struct CoroutineOnNonClosure { +pub(crate) struct CoroutineOnNonClosure { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_linkage)] -pub struct Linkage { +pub(crate) struct Linkage { #[primary_span] pub attr_span: Span, #[label] @@ -681,23 +690,23 @@ pub(crate) struct IncorrectMetaItemSuggestion { #[derive(Diagnostic)] #[diag(passes_stability_promotable)] -pub struct StabilityPromotable { +pub(crate) struct StabilityPromotable { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] #[diag(passes_deprecated)] -pub struct Deprecated; +pub(crate) struct Deprecated; #[derive(LintDiagnostic)] #[diag(passes_macro_use)] -pub struct MacroUse { +pub(crate) struct MacroUse { pub name: Symbol, } #[derive(LintDiagnostic)] -pub enum MacroExport { +pub(crate) enum MacroExport { #[diag(passes_macro_export)] Normal, @@ -713,7 +722,7 @@ pub enum MacroExport { } #[derive(Subdiagnostic)] -pub enum UnusedNote { +pub(crate) enum UnusedNote { #[note(passes_unused_empty_lints_note)] EmptyList { name: Symbol }, #[note(passes_unused_no_lints_note)] @@ -724,7 +733,7 @@ pub enum UnusedNote { #[derive(LintDiagnostic)] #[diag(passes_unused)] -pub struct Unused { +pub(crate) struct Unused { #[suggestion(code = "", applicability = "machine-applicable")] pub attr_span: Span, #[subdiagnostic] @@ -733,7 +742,7 @@ pub struct Unused { #[derive(Diagnostic)] #[diag(passes_non_exported_macro_invalid_attrs, code = E0518)] -pub struct NonExportedMacroInvalidAttrs { +pub(crate) struct NonExportedMacroInvalidAttrs { #[primary_span] #[label] pub attr_span: Span, @@ -741,14 +750,14 @@ pub struct NonExportedMacroInvalidAttrs { #[derive(Diagnostic)] #[diag(passes_may_dangle)] -pub struct InvalidMayDangle { +pub(crate) struct InvalidMayDangle { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] #[diag(passes_unused_duplicate)] -pub struct UnusedDuplicate { +pub(crate) struct UnusedDuplicate { #[suggestion(code = "", applicability = "machine-applicable")] pub this: Span, #[note] @@ -759,7 +768,7 @@ pub struct UnusedDuplicate { #[derive(Diagnostic)] #[diag(passes_unused_multiple)] -pub struct UnusedMultiple { +pub(crate) struct UnusedMultiple { #[primary_span] #[suggestion(code = "", applicability = "machine-applicable")] pub this: Span, @@ -770,7 +779,7 @@ pub struct UnusedMultiple { #[derive(Diagnostic)] #[diag(passes_rustc_lint_opt_ty)] -pub struct RustcLintOptTy { +pub(crate) struct RustcLintOptTy { #[primary_span] pub attr_span: Span, #[label] @@ -779,7 +788,7 @@ pub struct RustcLintOptTy { #[derive(Diagnostic)] #[diag(passes_rustc_lint_opt_deny_field_access)] -pub struct RustcLintOptDenyFieldAccess { +pub(crate) struct RustcLintOptDenyFieldAccess { #[primary_span] pub attr_span: Span, #[label] @@ -788,7 +797,7 @@ pub struct RustcLintOptDenyFieldAccess { #[derive(Diagnostic)] #[diag(passes_collapse_debuginfo)] -pub struct CollapseDebuginfo { +pub(crate) struct CollapseDebuginfo { #[primary_span] pub attr_span: Span, #[label] @@ -797,14 +806,14 @@ pub struct CollapseDebuginfo { #[derive(LintDiagnostic)] #[diag(passes_deprecated_annotation_has_no_effect)] -pub struct DeprecatedAnnotationHasNoEffect { +pub(crate) struct DeprecatedAnnotationHasNoEffect { #[suggestion(applicability = "machine-applicable", code = "")] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_unknown_external_lang_item, code = E0264)] -pub struct UnknownExternLangItem { +pub(crate) struct UnknownExternLangItem { #[primary_span] pub span: Span, pub lang_item: Symbol, @@ -812,25 +821,25 @@ pub struct UnknownExternLangItem { #[derive(Diagnostic)] #[diag(passes_missing_panic_handler)] -pub struct MissingPanicHandler; +pub(crate) struct MissingPanicHandler; #[derive(Diagnostic)] #[diag(passes_panic_unwind_without_std)] #[help] #[note] -pub struct PanicUnwindWithoutStd; +pub(crate) struct PanicUnwindWithoutStd; #[derive(Diagnostic)] #[diag(passes_missing_lang_item)] #[note] #[help] -pub struct MissingLangItem { +pub(crate) struct MissingLangItem { pub name: Symbol, } #[derive(Diagnostic)] #[diag(passes_lang_item_fn_with_track_caller)] -pub struct LangItemWithTrackCaller { +pub(crate) struct LangItemWithTrackCaller { #[primary_span] pub attr_span: Span, pub name: Symbol, @@ -840,7 +849,7 @@ pub struct LangItemWithTrackCaller { #[derive(Diagnostic)] #[diag(passes_lang_item_fn_with_target_feature)] -pub struct LangItemWithTargetFeature { +pub(crate) struct LangItemWithTargetFeature { #[primary_span] pub attr_span: Span, pub name: Symbol, @@ -850,7 +859,7 @@ pub struct LangItemWithTargetFeature { #[derive(Diagnostic)] #[diag(passes_lang_item_on_incorrect_target, code = E0718)] -pub struct LangItemOnIncorrectTarget { +pub(crate) struct LangItemOnIncorrectTarget { #[primary_span] #[label] pub span: Span, @@ -861,14 +870,14 @@ pub struct LangItemOnIncorrectTarget { #[derive(Diagnostic)] #[diag(passes_unknown_lang_item, code = E0522)] -pub struct UnknownLangItem { +pub(crate) struct UnknownLangItem { #[primary_span] #[label] pub span: Span, pub name: Symbol, } -pub struct InvalidAttrAtCrateLevel { +pub(crate) struct InvalidAttrAtCrateLevel { pub span: Span, pub sugg_span: Option<Span>, pub name: Symbol, @@ -876,7 +885,7 @@ pub struct InvalidAttrAtCrateLevel { } #[derive(Clone, Copy)] -pub struct ItemFollowingInnerAttr { +pub(crate) struct ItemFollowingInnerAttr { pub span: Span, pub kind: &'static str, } @@ -907,7 +916,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidAttrAtCrateLevel { #[derive(Diagnostic)] #[diag(passes_duplicate_diagnostic_item_in_crate)] -pub struct DuplicateDiagnosticItemInCrate { +pub(crate) struct DuplicateDiagnosticItemInCrate { #[primary_span] pub duplicate_span: Option<Span>, #[note(passes_diagnostic_item_first_defined)] @@ -921,7 +930,7 @@ pub struct DuplicateDiagnosticItemInCrate { #[derive(Diagnostic)] #[diag(passes_layout_abi)] -pub struct LayoutAbi { +pub(crate) struct LayoutAbi { #[primary_span] pub span: Span, pub abi: String, @@ -929,7 +938,7 @@ pub struct LayoutAbi { #[derive(Diagnostic)] #[diag(passes_layout_align)] -pub struct LayoutAlign { +pub(crate) struct LayoutAlign { #[primary_span] pub span: Span, pub align: String, @@ -937,7 +946,7 @@ pub struct LayoutAlign { #[derive(Diagnostic)] #[diag(passes_layout_size)] -pub struct LayoutSize { +pub(crate) struct LayoutSize { #[primary_span] pub span: Span, pub size: String, @@ -945,7 +954,7 @@ pub struct LayoutSize { #[derive(Diagnostic)] #[diag(passes_layout_homogeneous_aggregate)] -pub struct LayoutHomogeneousAggregate { +pub(crate) struct LayoutHomogeneousAggregate { #[primary_span] pub span: Span, pub homogeneous_aggregate: String, @@ -953,7 +962,7 @@ pub struct LayoutHomogeneousAggregate { #[derive(Diagnostic)] #[diag(passes_layout_of)] -pub struct LayoutOf { +pub(crate) struct LayoutOf { #[primary_span] pub span: Span, pub normalized_ty: String, @@ -962,14 +971,14 @@ pub struct LayoutOf { #[derive(Diagnostic)] #[diag(passes_layout_invalid_attribute)] -pub struct LayoutInvalidAttribute { +pub(crate) struct LayoutInvalidAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_abi_of)] -pub struct AbiOf { +pub(crate) struct AbiOf { #[primary_span] pub span: Span, pub fn_name: Symbol, @@ -978,7 +987,7 @@ pub struct AbiOf { #[derive(Diagnostic)] #[diag(passes_abi_ne)] -pub struct AbiNe { +pub(crate) struct AbiNe { #[primary_span] pub span: Span, pub left: String, @@ -987,14 +996,14 @@ pub struct AbiNe { #[derive(Diagnostic)] #[diag(passes_abi_invalid_attribute)] -pub struct AbiInvalidAttribute { +pub(crate) struct AbiInvalidAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_unrecognized_field)] -pub struct UnrecognizedField { +pub(crate) struct UnrecognizedField { #[primary_span] pub span: Span, pub name: Symbol, @@ -1002,7 +1011,7 @@ pub struct UnrecognizedField { #[derive(Diagnostic)] #[diag(passes_feature_stable_twice, code = E0711)] -pub struct FeatureStableTwice { +pub(crate) struct FeatureStableTwice { #[primary_span] pub span: Span, pub feature: Symbol, @@ -1012,7 +1021,7 @@ pub struct FeatureStableTwice { #[derive(Diagnostic)] #[diag(passes_feature_previously_declared, code = E0711)] -pub struct FeaturePreviouslyDeclared<'a, 'b> { +pub(crate) struct FeaturePreviouslyDeclared<'a, 'b> { #[primary_span] pub span: Span, pub feature: Symbol, @@ -1020,7 +1029,7 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> { pub prev_declared: &'b str, } -pub struct BreakNonLoop<'a> { +pub(crate) struct BreakNonLoop<'a> { pub span: Span, pub head: Option<Span>, pub kind: &'a str, @@ -1075,7 +1084,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { #[derive(Diagnostic)] #[diag(passes_continue_labeled_block, code = E0696)] -pub struct ContinueLabeledBlock { +pub(crate) struct ContinueLabeledBlock { #[primary_span] #[label] pub span: Span, @@ -1085,7 +1094,7 @@ pub struct ContinueLabeledBlock { #[derive(Diagnostic)] #[diag(passes_break_inside_closure, code = E0267)] -pub struct BreakInsideClosure<'a> { +pub(crate) struct BreakInsideClosure<'a> { #[primary_span] #[label] pub span: Span, @@ -1096,7 +1105,7 @@ pub struct BreakInsideClosure<'a> { #[derive(Diagnostic)] #[diag(passes_break_inside_coroutine, code = E0267)] -pub struct BreakInsideCoroutine<'a> { +pub(crate) struct BreakInsideCoroutine<'a> { #[primary_span] #[label] pub span: Span, @@ -1109,7 +1118,7 @@ pub struct BreakInsideCoroutine<'a> { #[derive(Diagnostic)] #[diag(passes_outside_loop, code = E0268)] -pub struct OutsideLoop<'a> { +pub(crate) struct OutsideLoop<'a> { #[primary_span] #[label] pub spans: Vec<Span>, @@ -1120,7 +1129,7 @@ pub struct OutsideLoop<'a> { } #[derive(Subdiagnostic)] #[multipart_suggestion(passes_outside_loop_suggestion, applicability = "maybe-incorrect")] -pub struct OutsideLoopSuggestion { +pub(crate) struct OutsideLoopSuggestion { #[suggestion_part(code = "'block: ")] pub block_span: Span, #[suggestion_part(code = " 'block")] @@ -1129,7 +1138,7 @@ pub struct OutsideLoopSuggestion { #[derive(Diagnostic)] #[diag(passes_unlabeled_in_labeled_block, code = E0695)] -pub struct UnlabeledInLabeledBlock<'a> { +pub(crate) struct UnlabeledInLabeledBlock<'a> { #[primary_span] #[label] pub span: Span, @@ -1138,7 +1147,7 @@ pub struct UnlabeledInLabeledBlock<'a> { #[derive(Diagnostic)] #[diag(passes_unlabeled_cf_in_while_condition, code = E0590)] -pub struct UnlabeledCfInWhileCondition<'a> { +pub(crate) struct UnlabeledCfInWhileCondition<'a> { #[primary_span] #[label] pub span: Span, @@ -1147,11 +1156,11 @@ pub struct UnlabeledCfInWhileCondition<'a> { #[derive(LintDiagnostic)] #[diag(passes_undefined_naked_function_abi)] -pub struct UndefinedNakedFunctionAbi; +pub(crate) struct UndefinedNakedFunctionAbi; #[derive(Diagnostic)] #[diag(passes_no_patterns)] -pub struct NoPatterns { +pub(crate) struct NoPatterns { #[primary_span] pub span: Span, } @@ -1159,12 +1168,12 @@ pub struct NoPatterns { #[derive(Diagnostic)] #[diag(passes_params_not_allowed)] #[help] -pub struct ParamsNotAllowed { +pub(crate) struct ParamsNotAllowed { #[primary_span] pub span: Span, } -pub struct NakedFunctionsAsmBlock { +pub(crate) struct NakedFunctionsAsmBlock { pub span: Span, pub multiple_asms: Vec<Span>, pub non_asms: Vec<Span>, @@ -1188,14 +1197,14 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for NakedFunctionsAsmBlock { #[derive(Diagnostic)] #[diag(passes_naked_functions_operands, code = E0787)] -pub struct NakedFunctionsOperands { +pub(crate) struct NakedFunctionsOperands { #[primary_span] pub unsupported_operands: Vec<Span>, } #[derive(Diagnostic)] #[diag(passes_naked_functions_asm_options, code = E0787)] -pub struct NakedFunctionsAsmOptions { +pub(crate) struct NakedFunctionsAsmOptions { #[primary_span] pub span: Span, pub unsupported_options: String, @@ -1203,7 +1212,7 @@ pub struct NakedFunctionsAsmOptions { #[derive(Diagnostic)] #[diag(passes_naked_functions_must_use_noreturn, code = E0787)] -pub struct NakedFunctionsMustUseNoreturn { +pub(crate) struct NakedFunctionsMustUseNoreturn { #[primary_span] pub span: Span, #[suggestion(code = ", options(noreturn)", applicability = "machine-applicable")] @@ -1212,7 +1221,7 @@ pub struct NakedFunctionsMustUseNoreturn { #[derive(Diagnostic)] #[diag(passes_naked_functions_incompatible_attribute, code = E0736)] -pub struct NakedFunctionIncompatibleAttribute { +pub(crate) struct NakedFunctionIncompatibleAttribute { #[primary_span] #[label] pub span: Span, @@ -1223,7 +1232,7 @@ pub struct NakedFunctionIncompatibleAttribute { #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] -pub struct AttrOnlyInFunctions { +pub(crate) struct AttrOnlyInFunctions { #[primary_span] pub span: Span, pub attr: Symbol, @@ -1231,7 +1240,7 @@ pub struct AttrOnlyInFunctions { #[derive(Diagnostic)] #[diag(passes_multiple_rustc_main, code = E0137)] -pub struct MultipleRustcMain { +pub(crate) struct MultipleRustcMain { #[primary_span] pub span: Span, #[label(passes_first)] @@ -1242,7 +1251,7 @@ pub struct MultipleRustcMain { #[derive(Diagnostic)] #[diag(passes_multiple_start_functions, code = E0138)] -pub struct MultipleStartFunctions { +pub(crate) struct MultipleStartFunctions { #[primary_span] pub span: Span, #[label] @@ -1253,12 +1262,12 @@ pub struct MultipleStartFunctions { #[derive(Diagnostic)] #[diag(passes_extern_main)] -pub struct ExternMain { +pub(crate) struct ExternMain { #[primary_span] pub span: Span, } -pub struct NoMainErr { +pub(crate) struct NoMainErr { pub sp: Span, pub crate_name: Symbol, pub has_filename: bool, @@ -1312,7 +1321,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { } } -pub struct DuplicateLangItem { +pub(crate) struct DuplicateLangItem { pub local_span: Option<Span>, pub lang_item_name: Symbol, pub crate_name: Symbol, @@ -1377,7 +1386,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem { #[derive(Diagnostic)] #[diag(passes_incorrect_target, code = E0718)] -pub struct IncorrectTarget<'a> { +pub(crate) struct IncorrectTarget<'a> { #[primary_span] pub span: Span, #[label] @@ -1391,21 +1400,21 @@ pub struct IncorrectTarget<'a> { #[derive(LintDiagnostic)] #[diag(passes_useless_assignment)] -pub struct UselessAssignment<'a> { +pub(crate) struct UselessAssignment<'a> { pub is_field_assign: bool, pub ty: Ty<'a>, } #[derive(LintDiagnostic)] #[diag(passes_only_has_effect_on)] -pub struct OnlyHasEffectOn { +pub(crate) struct OnlyHasEffectOn { pub attr_name: Symbol, pub target_name: String, } #[derive(Diagnostic)] #[diag(passes_object_lifetime_err)] -pub struct ObjectLifetimeErr { +pub(crate) struct ObjectLifetimeErr { #[primary_span] pub span: Span, pub repr: String, @@ -1414,13 +1423,13 @@ pub struct ObjectLifetimeErr { #[derive(Diagnostic)] #[diag(passes_unrecognized_repr_hint, code = E0552)] #[help] -pub struct UnrecognizedReprHint { +pub(crate) struct UnrecognizedReprHint { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -pub enum AttrApplication { +pub(crate) enum AttrApplication { #[diag(passes_attr_application_enum, code = E0517)] Enum { #[primary_span] @@ -1460,7 +1469,7 @@ pub enum AttrApplication { #[derive(Diagnostic)] #[diag(passes_transparent_incompatible, code = E0692)] -pub struct TransparentIncompatible { +pub(crate) struct TransparentIncompatible { #[primary_span] pub hint_spans: Vec<Span>, pub target: String, @@ -1468,14 +1477,14 @@ pub struct TransparentIncompatible { #[derive(Diagnostic)] #[diag(passes_deprecated_attribute, code = E0549)] -pub struct DeprecatedAttribute { +pub(crate) struct DeprecatedAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_useless_stability)] -pub struct UselessStability { +pub(crate) struct UselessStability { #[primary_span] #[label] pub span: Span, @@ -1485,7 +1494,7 @@ pub struct UselessStability { #[derive(Diagnostic)] #[diag(passes_cannot_stabilize_deprecated)] -pub struct CannotStabilizeDeprecated { +pub(crate) struct CannotStabilizeDeprecated { #[primary_span] #[label] pub span: Span, @@ -1495,7 +1504,7 @@ pub struct CannotStabilizeDeprecated { #[derive(Diagnostic)] #[diag(passes_missing_stability_attr)] -pub struct MissingStabilityAttr<'a> { +pub(crate) struct MissingStabilityAttr<'a> { #[primary_span] pub span: Span, pub descr: &'a str, @@ -1503,7 +1512,7 @@ pub struct MissingStabilityAttr<'a> { #[derive(Diagnostic)] #[diag(passes_missing_const_stab_attr)] -pub struct MissingConstStabAttr<'a> { +pub(crate) struct MissingConstStabAttr<'a> { #[primary_span] pub span: Span, pub descr: &'a str, @@ -1512,14 +1521,14 @@ pub struct MissingConstStabAttr<'a> { #[derive(Diagnostic)] #[diag(passes_trait_impl_const_stable)] #[note] -pub struct TraitImplConstStable { +pub(crate) struct TraitImplConstStable { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(passes_unknown_feature, code = E0635)] -pub struct UnknownFeature { +pub(crate) struct UnknownFeature { #[primary_span] pub span: Span, pub feature: Symbol, @@ -1527,7 +1536,7 @@ pub struct UnknownFeature { #[derive(Diagnostic)] #[diag(passes_implied_feature_not_exist)] -pub struct ImpliedFeatureNotExist { +pub(crate) struct ImpliedFeatureNotExist { #[primary_span] pub span: Span, pub feature: Symbol, @@ -1536,14 +1545,14 @@ pub struct ImpliedFeatureNotExist { #[derive(Diagnostic)] #[diag(passes_duplicate_feature_err, code = E0636)] -pub struct DuplicateFeatureErr { +pub(crate) struct DuplicateFeatureErr { #[primary_span] pub span: Span, pub feature: Symbol, } #[derive(Diagnostic)] #[diag(passes_missing_const_err)] -pub struct MissingConstErr { +pub(crate) struct MissingConstErr { #[primary_span] #[help] pub fn_sig_span: Span, @@ -1552,7 +1561,7 @@ pub struct MissingConstErr { } #[derive(LintDiagnostic)] -pub enum MultipleDeadCodes<'tcx> { +pub(crate) enum MultipleDeadCodes<'tcx> { #[diag(passes_dead_codes)] DeadCodes { multiple: bool, @@ -1583,7 +1592,7 @@ pub enum MultipleDeadCodes<'tcx> { #[derive(Subdiagnostic)] #[label(passes_parent_info)] -pub struct ParentInfo<'tcx> { +pub(crate) struct ParentInfo<'tcx> { pub num: usize, pub descr: &'tcx str, pub parent_descr: &'tcx str, @@ -1593,14 +1602,14 @@ pub struct ParentInfo<'tcx> { #[derive(Subdiagnostic)] #[note(passes_ignored_derived_impls)] -pub struct IgnoredDerivedImpls { +pub(crate) struct IgnoredDerivedImpls { pub name: Symbol, pub trait_list: DiagSymbolList, pub trait_list_len: usize, } #[derive(Subdiagnostic)] -pub enum ChangeFields { +pub(crate) enum ChangeFields { #[multipart_suggestion( passes_change_fields_to_be_of_unit_type, applicability = "has-placeholders" @@ -1624,14 +1633,14 @@ pub(crate) struct ProcMacroBadSig { #[derive(Diagnostic)] #[diag(passes_skipping_const_checks)] -pub struct SkippingConstChecks { +pub(crate) struct SkippingConstChecks { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] #[diag(passes_unreachable_due_to_uninhabited)] -pub struct UnreachableDueToUninhabited<'desc, 'tcx> { +pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> { pub descr: &'desc str, #[label] pub expr: Span, @@ -1644,20 +1653,20 @@ pub struct UnreachableDueToUninhabited<'desc, 'tcx> { #[derive(LintDiagnostic)] #[diag(passes_unused_var_maybe_capture_ref)] #[help] -pub struct UnusedVarMaybeCaptureRef { +pub(crate) struct UnusedVarMaybeCaptureRef { pub name: String, } #[derive(LintDiagnostic)] #[diag(passes_unused_capture_maybe_capture_ref)] #[help] -pub struct UnusedCaptureMaybeCaptureRef { +pub(crate) struct UnusedCaptureMaybeCaptureRef { pub name: String, } #[derive(LintDiagnostic)] #[diag(passes_unused_var_remove_field)] -pub struct UnusedVarRemoveField { +pub(crate) struct UnusedVarRemoveField { pub name: String, #[subdiagnostic] pub sugg: UnusedVarRemoveFieldSugg, @@ -1668,7 +1677,7 @@ pub struct UnusedVarRemoveField { passes_unused_var_remove_field_suggestion, applicability = "machine-applicable" )] -pub struct UnusedVarRemoveFieldSugg { +pub(crate) struct UnusedVarRemoveFieldSugg { #[suggestion_part(code = "")] pub spans: Vec<Span>, } @@ -1676,20 +1685,20 @@ pub struct UnusedVarRemoveFieldSugg { #[derive(LintDiagnostic)] #[diag(passes_unused_var_assigned_only)] #[note] -pub struct UnusedVarAssignedOnly { +pub(crate) struct UnusedVarAssignedOnly { pub name: String, } #[derive(LintDiagnostic)] #[diag(passes_unnecessary_stable_feature)] -pub struct UnnecessaryStableFeature { +pub(crate) struct UnnecessaryStableFeature { pub feature: Symbol, pub since: Symbol, } #[derive(LintDiagnostic)] #[diag(passes_unnecessary_partial_stable_feature)] -pub struct UnnecessaryPartialStableFeature { +pub(crate) struct UnnecessaryPartialStableFeature { #[suggestion(code = "{implies}", applicability = "maybe-incorrect")] pub span: Span, #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")] @@ -1702,25 +1711,25 @@ pub struct UnnecessaryPartialStableFeature { #[derive(LintDiagnostic)] #[diag(passes_ineffective_unstable_impl)] #[note] -pub struct IneffectiveUnstableImpl; +pub(crate) struct IneffectiveUnstableImpl; #[derive(LintDiagnostic)] #[diag(passes_unused_assign)] #[help] -pub struct UnusedAssign { +pub(crate) struct UnusedAssign { pub name: String, } #[derive(LintDiagnostic)] #[diag(passes_unused_assign_passed)] #[help] -pub struct UnusedAssignPassed { +pub(crate) struct UnusedAssignPassed { pub name: String, } #[derive(LintDiagnostic)] #[diag(passes_unused_variable_try_prefix)] -pub struct UnusedVariableTryPrefix { +pub(crate) struct UnusedVariableTryPrefix { #[label] pub label: Option<Span>, #[subdiagnostic] @@ -1731,7 +1740,7 @@ pub struct UnusedVariableTryPrefix { } #[derive(Subdiagnostic)] -pub enum UnusedVariableSugg { +pub(crate) enum UnusedVariableSugg { #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] TryPrefixSugg { #[suggestion_part(code = "_{name}")] @@ -1746,7 +1755,7 @@ pub enum UnusedVariableSugg { }, } -pub struct UnusedVariableStringInterp { +pub(crate) struct UnusedVariableStringInterp { pub lit: Span, pub lo: Span, pub hi: Span, @@ -1769,14 +1778,14 @@ impl Subdiagnostic for UnusedVariableStringInterp { #[derive(LintDiagnostic)] #[diag(passes_unused_variable_try_ignore)] -pub struct UnusedVarTryIgnore { +pub(crate) struct UnusedVarTryIgnore { #[subdiagnostic] pub sugg: UnusedVarTryIgnoreSugg, } #[derive(Subdiagnostic)] #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] -pub struct UnusedVarTryIgnoreSugg { +pub(crate) struct UnusedVarTryIgnoreSugg { #[suggestion_part(code = "{name}: _")] pub shorthands: Vec<Span>, #[suggestion_part(code = "_")] @@ -1787,14 +1796,14 @@ pub struct UnusedVarTryIgnoreSugg { #[derive(LintDiagnostic)] #[diag(passes_attr_crate_level)] #[note] -pub struct AttrCrateLevelOnly { +pub(crate) struct AttrCrateLevelOnly { #[subdiagnostic] pub sugg: Option<AttrCrateLevelOnlySugg>, } #[derive(Subdiagnostic)] #[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")] -pub struct AttrCrateLevelOnlySugg { +pub(crate) struct AttrCrateLevelOnlySugg { #[primary_span] pub attr: Span, } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 71b0ebb0e21..8038afb955e 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -359,6 +359,6 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { } } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.get_lang_items = get_lang_items; } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index a0f5f98aafc..664da65068d 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,6 +12,7 @@ #![feature(map_try_insert)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::query::Providers; diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index e60985ba16f..9d5766865c7 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -16,7 +16,7 @@ use rustc_span::{sym, Span}; use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice}; -pub struct LibFeatureCollector<'tcx> { +struct LibFeatureCollector<'tcx> { tcx: TyCtxt<'tcx>, lib_features: LibFeatures, } @@ -153,6 +153,6 @@ fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures { collector.lib_features } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.lib_features = lib_features; } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index d3b85da4630..db3eaea68b5 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -178,7 +178,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { lsets.warn_about_unused_args(&body, entry_ln); } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_liveness, ..*providers }; } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index dee8ba7e87d..8d9e00b9f3c 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -500,6 +500,6 @@ fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet { reachable_context.reachable_symbols } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { reachable_set, ..*providers }; } diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index f2454514e4d..0544d08f5b1 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -9,7 +9,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::Span; -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { providers.upvars_mentioned = |tcx, def_id| { if !tcx.is_closure_like(def_id) { return None; diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 90691ca1790..020128f29c5 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -15,7 +15,11 @@ use crate::errors::{ /// Checks the crate for usage of weak lang items, returning a vector of all the /// lang items required by this crate, but not defined yet. -pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems, krate: &ast::Crate) { +pub(crate) fn check_crate( + tcx: TyCtxt<'_>, + items: &mut lang_items::LanguageItems, + krate: &ast::Crate, +) { // These are never called by user code, they're generated by the compiler. // They will never implicitly be added to the `missing` array unless we do // so here. diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 6c9c848bb10..fec44d5af55 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -6,6 +6,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![cfg_attr(feature = "rustc", feature(let_chains))] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod constructor; diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 89face10750..34553c2b90a 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -5,7 +5,7 @@ use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag(privacy_field_is_private, code = E0451)] -pub struct FieldIsPrivate { +pub(crate) struct FieldIsPrivate { #[primary_span] pub span: Span, pub field_name: Symbol, @@ -16,7 +16,7 @@ pub struct FieldIsPrivate { } #[derive(Subdiagnostic)] -pub enum FieldIsPrivateLabel { +pub(crate) enum FieldIsPrivateLabel { #[label(privacy_field_is_private_is_update_syntax_label)] IsUpdateSyntax { #[primary_span] @@ -32,7 +32,7 @@ pub enum FieldIsPrivateLabel { #[derive(Diagnostic)] #[diag(privacy_item_is_private)] -pub struct ItemIsPrivate<'a> { +pub(crate) struct ItemIsPrivate<'a> { #[primary_span] #[label] pub span: Span, @@ -42,7 +42,7 @@ pub struct ItemIsPrivate<'a> { #[derive(Diagnostic)] #[diag(privacy_unnamed_item_is_private)] -pub struct UnnamedItemIsPrivate { +pub(crate) struct UnnamedItemIsPrivate { #[primary_span] pub span: Span, pub kind: &'static str, @@ -50,7 +50,7 @@ pub struct UnnamedItemIsPrivate { #[derive(Diagnostic)] #[diag(privacy_in_public_interface, code = E0446)] -pub struct InPublicInterface<'a> { +pub(crate) struct InPublicInterface<'a> { #[primary_span] #[label] pub span: Span, @@ -63,7 +63,7 @@ pub struct InPublicInterface<'a> { #[derive(Diagnostic)] #[diag(privacy_report_effective_visibility)] -pub struct ReportEffectiveVisibility { +pub(crate) struct ReportEffectiveVisibility { #[primary_span] pub span: Span, pub descr: String, @@ -71,7 +71,7 @@ pub struct ReportEffectiveVisibility { #[derive(LintDiagnostic)] #[diag(privacy_from_private_dep_in_public_interface)] -pub struct FromPrivateDependencyInPublicInterface<'a> { +pub(crate) struct FromPrivateDependencyInPublicInterface<'a> { pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, pub krate: Symbol, @@ -79,7 +79,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> { #[derive(LintDiagnostic)] #[diag(privacy_unnameable_types_lint)] -pub struct UnnameableTypesLint<'a> { +pub(crate) struct UnnameableTypesLint<'a> { #[label] pub span: Span, pub kind: &'a str, @@ -93,7 +93,7 @@ pub struct UnnameableTypesLint<'a> { // See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details. #[derive(LintDiagnostic)] #[diag(privacy_private_interface_or_bounds_lint)] -pub struct PrivateInterfacesOrBoundsLint<'a> { +pub(crate) struct PrivateInterfacesOrBoundsLint<'a> { #[label(privacy_item_label)] pub item_span: Span, pub item_kind: &'a str, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9f78215bfd1..572f71d7c77 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -6,6 +6,7 @@ #![feature(let_chains)] #![feature(rustdoc_internals)] #![feature(try_blocks)] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod errors; @@ -1497,7 +1498,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { self.effective_visibilities.effective_vis(def_id).copied() } - pub fn check_item(&mut self, id: ItemId) { + fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index f4a4c602f69..a6c863a6b7b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -8,6 +8,7 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use field_offset::offset_of; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index c064b2bd6c1..6a6698b019c 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -541,7 +541,7 @@ macro_rules! expand_if_cached { /// Don't show the backtrace for query system by default /// use `RUST_BACKTRACE=full` to show all the backtraces #[inline(never)] -pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T +pub(crate) fn __rust_begin_short_backtrace<F, T>(f: F) -> T where F: FnOnce() -> T, { @@ -557,17 +557,17 @@ macro_rules! define_queries { $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - pub(crate) mod query_impl { $(pub mod $name { + pub(crate) mod query_impl { $(pub(crate) mod $name { use super::super::*; use std::marker::PhantomData; - pub mod get_query_incr { + pub(crate) mod get_query_incr { use super::*; // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming #[inline(never)] - pub fn __rust_end_short_backtrace<'tcx>( + pub(crate) fn __rust_end_short_backtrace<'tcx>( tcx: TyCtxt<'tcx>, span: Span, key: queries::$name::Key<'tcx>, @@ -585,11 +585,11 @@ macro_rules! define_queries { } } - pub mod get_query_non_incr { + pub(crate) mod get_query_non_incr { use super::*; #[inline(never)] - pub fn __rust_end_short_backtrace<'tcx>( + pub(crate) fn __rust_end_short_backtrace<'tcx>( tcx: TyCtxt<'tcx>, span: Span, key: queries::$name::Key<'tcx>, @@ -604,7 +604,9 @@ macro_rules! define_queries { } } - pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> { + pub(crate) fn dynamic_query<'tcx>() + -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> + { DynamicQuery { name: stringify!($name), eval_always: is_eval_always!([$($modifiers)*]), @@ -667,7 +669,7 @@ macro_rules! define_queries { } #[derive(Copy, Clone, Default)] - pub struct QueryType<'tcx> { + pub(crate) struct QueryType<'tcx> { data: PhantomData<&'tcx ()> } @@ -696,7 +698,7 @@ macro_rules! define_queries { } } - pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { + pub(crate) fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { let make_query = |tcx, key| { let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); @@ -711,11 +713,17 @@ macro_rules! define_queries { // don't `unwrap()` here, just manually check for `None` and do best-effort error // reporting. if res.is_none() { - tracing::warn!("Failed to collect active jobs for query with name `{}`!", stringify!($name)); + tracing::warn!( + "Failed to collect active jobs for query with name `{}`!", + stringify!($name) + ); } } - pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) { + pub(crate) fn alloc_self_profile_query_strings<'tcx>( + tcx: TyCtxt<'tcx>, + string_cache: &mut QueryKeyStringCache + ) { $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( tcx, stringify!($name), @@ -725,7 +733,7 @@ macro_rules! define_queries { } item_if_cached! { [$($modifiers)*] { - pub fn encode_query_results<'tcx>( + pub(crate) fn encode_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex @@ -739,7 +747,7 @@ macro_rules! define_queries { } }} - pub fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { + pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { $crate::plumbing::query_key_hash_verify( query_impl::$name::QueryType::config(tcx), QueryCtxt::new(tcx), @@ -795,7 +803,7 @@ macro_rules! define_queries { use rustc_query_system::dep_graph::FingerprintStyle; // We use this for most things when incr. comp. is turned off. - pub fn Null<'tcx>() -> DepKindStruct<'tcx> { + pub(crate) fn Null<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: false, is_eval_always: false, @@ -807,7 +815,7 @@ macro_rules! define_queries { } // We use this for the forever-red node. - pub fn Red<'tcx>() -> DepKindStruct<'tcx> { + pub(crate) fn Red<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: false, is_eval_always: false, @@ -818,7 +826,7 @@ macro_rules! define_queries { } } - pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> { + pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: true, is_eval_always: false, @@ -829,7 +837,7 @@ macro_rules! define_queries { } } - pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> { + pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: false, is_eval_always: false, @@ -840,7 +848,7 @@ macro_rules! define_queries { } } - pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> { + pub(crate) fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: false, is_eval_always: false, diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index ab4a8be0fbf..a4fb0a5b072 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -617,14 +617,14 @@ impl<D: Deps> EncoderState<D> { } } -pub struct GraphEncoder<D: Deps> { +pub(crate) struct GraphEncoder<D: Deps> { profiler: SelfProfilerRef, status: Lock<Option<EncoderState<D>>>, record_graph: Option<Lock<DepGraphQuery>>, } impl<D: Deps> GraphEncoder<D> { - pub fn new( + pub(crate) fn new( encoder: FileEncoder, prev_node_count: usize, record_graph: bool, @@ -723,7 +723,7 @@ impl<D: Deps> GraphEncoder<D> { ) } - pub fn finish(&self) -> FileEncodeResult { + pub(crate) fn finish(&self) -> FileEncodeResult { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph_finish"); self.status.lock().take().unwrap().finish(&self.profiler) diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 9db6fac8036..860f2e66915 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -5,7 +5,7 @@ use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] #[note(query_system_cycle_stack_middle)] -pub struct CycleStack { +pub(crate) struct CycleStack { #[primary_span] pub span: Span, pub desc: String, @@ -20,7 +20,7 @@ pub enum HandleCycleError { } #[derive(Subdiagnostic)] -pub enum StackCount { +pub(crate) enum StackCount { #[note(query_system_cycle_stack_single)] Single, #[note(query_system_cycle_stack_multiple)] @@ -28,7 +28,7 @@ pub enum StackCount { } #[derive(Subdiagnostic)] -pub enum Alias { +pub(crate) enum Alias { #[note(query_system_cycle_recursive_ty_alias)] #[help(query_system_cycle_recursive_ty_alias_help1)] #[help(query_system_cycle_recursive_ty_alias_help2)] @@ -39,7 +39,7 @@ pub enum Alias { #[derive(Subdiagnostic)] #[note(query_system_cycle_usage)] -pub struct CycleUsage { +pub(crate) struct CycleUsage { #[primary_span] pub span: Span, pub usage: String, @@ -47,7 +47,7 @@ pub struct CycleUsage { #[derive(Diagnostic)] #[diag(query_system_cycle, code = E0391)] -pub struct Cycle { +pub(crate) struct Cycle { #[primary_span] pub span: Span, pub stack_bottom: String, @@ -65,14 +65,14 @@ pub struct Cycle { #[derive(Diagnostic)] #[diag(query_system_reentrant)] -pub struct Reentrant; +pub(crate) struct Reentrant; #[derive(Diagnostic)] #[diag(query_system_increment_compilation)] #[help] #[note(query_system_increment_compilation_note1)] #[note(query_system_increment_compilation_note2)] -pub struct IncrementCompilation { +pub(crate) struct IncrementCompilation { pub run_cmd: String, pub dep_node: String, } diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 7a50a9534c2..ba7a631fb54 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -5,6 +5,7 @@ #![feature(hash_raw_entry)] #![feature(let_chains)] #![feature(min_specialization)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod cache; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 02fdc1ae668..8ffd00d1b2e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -21,6 +21,7 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::cell::{Cell, RefCell}; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 95d171409d8..fbdb3cb1534 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -22,7 +22,9 @@ use rustc_feature::UnstableFeatures; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; -use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm}; +use rustc_span::{ + sym, FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm, Symbol, +}; use rustc_target::spec::{ FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTriple, }; @@ -402,6 +404,23 @@ impl LocationDetail { } } +/// Values for the `-Z fmt-debug` flag. +#[derive(Copy, Clone, PartialEq, Hash, Debug)] +pub enum FmtDebug { + /// Derive fully-featured implementation + Full, + /// Print only type name, without fields + Shallow, + /// `#[derive(Debug)]` and `{:?}` are no-ops + None, +} + +impl FmtDebug { + pub(crate) fn all() -> [Symbol; 3] { + [sym::full, sym::none, sym::shallow] + } +} + #[derive(Clone, PartialEq, Hash, Debug)] pub enum SwitchWithOptPath { Enabled(Option<PathBuf>), @@ -2893,6 +2912,7 @@ pub enum PpHirMode { } #[derive(Copy, Clone, PartialEq, Debug)] +/// Pretty print mode pub enum PpMode { /// Options that print the source code, i.e. /// `-Zunpretty=normal` and `-Zunpretty=expanded` @@ -2993,7 +3013,7 @@ pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, - CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn, + CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks, @@ -3087,6 +3107,7 @@ pub(crate) mod dep_tracking { OutputType, RealFileName, LocationDetail, + FmtDebug, BranchProtection, OomStrategy, LanguageIdentifier, diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index a64b1e21e9e..0fa776ecb5c 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -31,7 +31,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::Align; use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target, TargetTriple, TARGETS}; -use crate::config::CrateType; +use crate::config::{CrateType, FmtDebug}; use crate::Session; /// The parsed `--cfg` options that define the compilation environment of the @@ -142,6 +142,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_has_atomic_equal_alignment, Some(_)) | (sym::target_has_atomic_load_store, Some(_)) | (sym::target_thread_local, None) => disallow(cfg, "--target"), + (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"), _ => {} } } @@ -179,6 +180,20 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_none!(sym::debug_assertions); } + if sess.is_nightly_build() { + match sess.opts.unstable_opts.fmt_debug { + FmtDebug::Full => { + ins_sym!(sym::fmt_debug, sym::full); + } + FmtDebug::Shallow => { + ins_sym!(sym::fmt_debug, sym::shallow); + } + FmtDebug::None => { + ins_sym!(sym::fmt_debug, sym::none); + } + } + } + if sess.overflow_checks() { ins_none!(sym::overflow_checks); } @@ -326,6 +341,8 @@ impl CheckCfg { ins!(sym::debug_assertions, no_values); + ins!(sym::fmt_debug, empty_values).extend(FmtDebug::all()); + // These four are never set by rustc, but we set them anyway; they // should not trigger the lint because `cargo clippy`, `cargo doc`, // `cargo test`, `cargo miri run` and `cargo fmt` (respectively) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 23231fbffbf..4492ad09357 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -408,6 +408,7 @@ mod desc { pub const parse_linker_plugin_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin"; pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`"; + pub const parse_fmt_debug: &str = "either `full`, `shallow`, or `none`"; pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; @@ -589,6 +590,16 @@ mod parse { } } + pub(crate) fn parse_fmt_debug(opt: &mut FmtDebug, v: Option<&str>) -> bool { + *opt = match v { + Some("full") => FmtDebug::Full, + Some("shallow") => FmtDebug::Shallow, + Some("none") => FmtDebug::None, + _ => return false, + }; + true + } + pub(crate) fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool { if let Some(v) = v { ld.line = false; @@ -1724,6 +1735,9 @@ options! { flatten_format_args: bool = (true, parse_bool, [TRACKED], "flatten nested format_args!() and literals into a simplified format_args!() call \ (default: yes)"), + fmt_debug: FmtDebug = (FmtDebug::Full, parse_fmt_debug, [TRACKED], + "how detailed `#[derive(Debug)]` should be. `full` prints types recursively, \ + `shallow` prints only type names, `none` prints nothing and disables `{:?}`. (default: `full`)"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable (default: no)"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], @@ -1797,6 +1811,8 @@ options! { "link the `.rlink` file generated by `-Z no-link` (default: no)"), linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED], "a comma-separated list of linker features to enable (+) or disable (-): `lld`"), + lint_llvm_ir: bool = (false, parse_bool, [TRACKED], + "lint LLVM IR (default: no)"), lint_mir: bool = (false, parse_bool, [UNTRACKED], "lint MIR before and after each transformation"), llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED], diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 35fe28c5d42..7b020f11cdd 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -26,7 +26,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(read_buf)] #![feature(round_char_boundary)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2957105288b..16f5e55835e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -356,6 +356,7 @@ symbols! { _task_context, a32, aarch64_target_feature, + aarch64_unstable_target_feature, aarch64_ver_target_feature, abi, abi_amdgpu_kernel, @@ -535,6 +536,7 @@ symbols! { cfg_attr_multi, cfg_doctest, cfg_eval, + cfg_fmt_debug, cfg_hide, cfg_overflow_checks, cfg_panic, @@ -894,6 +896,7 @@ symbols! { fmaf32, fmaf64, fmt, + fmt_debug, fmul_algebraic, fmul_fast, fn_align, @@ -937,6 +940,7 @@ symbols! { fs_create_dir, fsub_algebraic, fsub_fast, + full, fundamental, fused_iterator, future, @@ -1280,6 +1284,7 @@ symbols! { new_binary, new_const, new_debug, + new_debug_noop, new_display, new_lower_exp, new_lower_hex, @@ -1714,6 +1719,7 @@ symbols! { semitransparent, sha512_sm_x86, shadow_call_stack, + shallow, shl, shl_assign, shorter_tail_lifetimes, @@ -1852,6 +1858,7 @@ symbols! { stringify, struct_field_attributes, struct_inherit, + struct_target_features, struct_variant, structural_match, structural_peq, @@ -1896,6 +1903,7 @@ symbols! { three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, tmm_reg, to_owned_method, to_string, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 1525faf9b7e..9fd7c246498 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -7,7 +7,7 @@ pub fn target() -> Target { llvm_target: "aarch64-unknown-unknown-musl".into(), metadata: crate::spec::TargetMetadata { description: Some("ARM64 Trusty".into()), - tier: Some(2), + tier: Some(3), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs index ae73de5e64d..889cc201569 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { llvm_target: "armv7-unknown-unknown-gnueabi".into(), metadata: crate::spec::TargetMetadata { description: Some("Armv7-A Trusty".into()), - tier: Some(2), + tier: Some(3), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs index bfd88bd042e..61226809e52 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs @@ -28,7 +28,7 @@ pub fn target() -> Target { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, eh_frame_header: false, - supported_sanitizers: SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KERNELADDRESS | SanitizerSet::SHADOWCALLSTACK, ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs index fa3f1eff457..b7444df04cd 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs @@ -27,7 +27,7 @@ pub fn target() -> Target { code_model: Some(CodeModel::Medium), emit_debug_gdb_scripts: false, eh_frame_header: false, - supported_sanitizers: SanitizerSet::KERNELADDRESS, + supported_sanitizers: SanitizerSet::KERNELADDRESS | SanitizerSet::SHADOWCALLSTACK, ..Default::default() }, } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index da66ba270b3..8319cb880cc 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -99,6 +99,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("bti", Stable, &[]), // FEAT_CRC ("crc", Stable, &[]), + // FEAT_CSSC + ("cssc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_DIT ("dit", Stable, &[]), // FEAT_DotProd @@ -107,21 +109,37 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("dpb", Stable, &[]), // FEAT_DPB2 ("dpb2", Stable, &["dpb"]), + // FEAT_ECV + ("ecv", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_F32MM ("f32mm", Stable, &["sve"]), // FEAT_F64MM ("f64mm", Stable, &["sve"]), + // FEAT_FAMINMAX + ("faminmax", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FCMA ("fcma", Stable, &["neon"]), // FEAT_FHM ("fhm", Stable, &["fp16"]), // FEAT_FLAGM ("flagm", Stable, &[]), + // FEAT_FLAGM2 + ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 ("fp16", Stable, &["neon"]), + // FEAT_FP8 + ("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]), + // FEAT_FP8DOT2 + ("fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["fp8dot4"]), + // FEAT_FP8DOT4 + ("fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["fp8fma"]), + // FEAT_FP8FMA + ("fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["fp8"]), // FEAT_FRINTTS ("frintts", Stable, &[]), + // FEAT_HBC + ("hbc", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_I8MM ("i8mm", Stable, &[]), // FEAT_JSCVT @@ -131,6 +149,14 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lor", Stable, &[]), // FEAT_LSE ("lse", Stable, &[]), + // FEAT_LSE128 + ("lse128", Unstable(sym::aarch64_unstable_target_feature), &["lse"]), + // FEAT_LSE2 + ("lse2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_LUT + ("lut", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_MOPS + ("mops", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_MTE & FEAT_MTE2 ("mte", Stable, &[]), // FEAT_AdvSimd & FEAT_FP @@ -143,14 +169,16 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("pan", Stable, &[]), // FEAT_PMUv3 ("pmuv3", Stable, &[]), - // FEAT_RAND + // FEAT_RNG ("rand", Stable, &[]), // FEAT_RAS & FEAT_RASv1p1 ("ras", Stable, &[]), - // FEAT_RCPC + // FEAT_LRCPC ("rcpc", Stable, &[]), - // FEAT_RCPC2 + // FEAT_LRCPC2 ("rcpc2", Stable, &["rcpc"]), + // FEAT_LRCPC3 + ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), // FEAT_SB @@ -161,10 +189,36 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sha3", Stable, &["sha2"]), // FEAT_SM3 & FEAT_SM4 ("sm4", Stable, &["neon"]), + // FEAT_SME + ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_F16F16 + ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), + // FEAT_SME_F64F64 + ("sme-f64f64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_F8F16 + ("sme-f8f16", Unstable(sym::aarch64_unstable_target_feature), &["sme-f8f32"]), + // FEAT_SME_F8F32 + ("sme-f8f32", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), + // FEAT_SME_FA64 + ("sme-fa64", Unstable(sym::aarch64_unstable_target_feature), &["sme", "sve2"]), + // FEAT_SME_I16I64 + ("sme-i16i64", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME_LUTv2 + ("sme-lutv2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // FEAT_SME2 + ("sme2", Unstable(sym::aarch64_unstable_target_feature), &["sme"]), + // FEAT_SME2p1 + ("sme2p1", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SPE ("spe", Stable, &[]), // FEAT_SSBS & FEAT_SSBS2 ("ssbs", Stable, &[]), + // FEAT_SSVE_FP8FDOT2 + ("ssve-fp8dot2", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8dot4"]), + // FEAT_SSVE_FP8FDOT4 + ("ssve-fp8dot4", Unstable(sym::aarch64_unstable_target_feature), &["ssve-fp8fma"]), + // FEAT_SSVE_FP8FMA + ("ssve-fp8fma", Unstable(sym::aarch64_unstable_target_feature), &["sme2", "fp8"]), // FEAT_SVE // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608 // @@ -173,9 +227,11 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), + // FEAT_SVE_B16B16 (SVE or SME Instructions) + ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), - // FEAT_SVE2_AES + // FEAT_SVE_AES & FEAT_SVE_PMULL128 ("sve2-aes", Stable, &["sve2", "aes"]), // FEAT_SVE2_BitPerm ("sve2-bitperm", Stable, &["sve2"]), @@ -183,6 +239,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sve2-sha3", Stable, &["sve2", "sha3"]), // FEAT_SVE2_SM4 ("sve2-sm4", Stable, &["sve2", "sm4"]), + // FEAT_SVE2p1 + ("sve2p1", Unstable(sym::aarch64_unstable_target_feature), &["sve2"]), // FEAT_TME ("tme", Stable, &[]), ( @@ -199,9 +257,19 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]), ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]), ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]), - ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &["v8.6a", "wfxt"]), + ("v8.8a", Unstable(sym::aarch64_ver_target_feature), &["v8.7a", "hbc", "mops"]), + ("v8.9a", Unstable(sym::aarch64_ver_target_feature), &["v8.8a", "cssc"]), + ("v9.1a", Unstable(sym::aarch64_ver_target_feature), &["v9a", "v8.6a"]), + ("v9.2a", Unstable(sym::aarch64_ver_target_feature), &["v9.1a", "v8.7a"]), + ("v9.3a", Unstable(sym::aarch64_ver_target_feature), &["v9.2a", "v8.8a"]), + ("v9.4a", Unstable(sym::aarch64_ver_target_feature), &["v9.3a", "v8.9a"]), + ("v9.5a", Unstable(sym::aarch64_ver_target_feature), &["v9.4a"]), + ("v9a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "sve2"]), // FEAT_VHE ("vh", Stable, &[]), + // FEAT_WFxT + ("wfxt", Unstable(sym::aarch64_unstable_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 137850f31d3..3ddd23924b5 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -446,6 +446,8 @@ trait_selection_type_annotations_needed = {$source_kind -> } .label = type must be known at this point +trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + trait_selection_types_declared_different = these two types are declared with different lifetimes... trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 173671059ca..53f013ac153 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -6,7 +6,7 @@ use rustc_errors::codes::*; use rustc_errors::{Diag, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource}; use rustc_middle::bug; @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -384,6 +384,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label, was_written: false, path: Default::default(), + time_version: false, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -577,6 +578,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } + + let time_version = + self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags); + match error_code { TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired { span, @@ -588,6 +593,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { bad_label: None, was_written: path.is_some(), path: path.unwrap_or_default(), + time_version, }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -613,6 +619,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }), } } + + /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error. + /// <https://github.com/rust-lang/rust/issues/127343> + // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself. + fn detect_old_time_crate_version( + &self, + span: Option<Span>, + kind: &InferSourceKind<'_>, + // We will clear the non-actionable suggestion from the error to reduce noise. + infer_subdiags: &mut Vec<SourceKindSubdiag<'_>>, + ) -> bool { + // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing + // compilation once we promote 1.89 to beta, which will happen in 9 months from now. + #[cfg(not(version("1.89")))] + const fn version_check() {} + #[cfg(version("1.89"))] + const fn version_check() { + panic!("remove this check as presumably the ecosystem has moved from needing it"); + } + const { version_check() }; + // Only relevant when building the `time` crate. + if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time + && let Some(span) = span + && let InferSourceKind::LetBinding { pattern_name, .. } = kind + && let Some(name) = pattern_name + && name.as_str() == "items" + && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span) + { + let path = file.local_path_if_available().to_string_lossy(); + if path.contains("format_description") && path.contains("parse") { + infer_subdiags.clear(); + return true; + } + } + false + } } #[derive(Debug)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 9f0282319ec..def9d6e9a31 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -438,6 +438,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_target_feature_fn = if let ty::FnDef(def_id, _) = *leaf_trait_ref.skip_binder().self_ty().kind() { + // FIXME(struct_target_features): should a function that inherits + // target_features through arguments implement Fn traits? !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { false diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5384084f6d7..ebaec0b9059 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -205,6 +205,8 @@ pub struct AnnotationRequired<'a> { #[note(trait_selection_full_type_written)] pub was_written: bool, pub path: PathBuf, + #[note(trait_selection_type_annotations_needed_error_time)] + pub time_version: bool, } // Copy of `AnnotationRequired` for E0283 diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1bd66266936..c98d6c5f1df 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -19,6 +19,7 @@ #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] +#![feature(cfg_version)] #![feature(control_flow_enum)] #![feature(extract_if)] #![feature(if_let_guard)] diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cb8deeaedb6..a21feec4b1a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -545,6 +545,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). ty::FnDef(def_id, args) => { let tcx = self.tcx(); + // FIXME(struct_target_features): should a function that inherits target_features + // through an argument implement Fn traits? if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 328b6739d97..80c3565911e 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -254,13 +254,6 @@ pub enum TyKind<I: Interner> { Error(I::ErrorGuaranteed), } -impl<I: Interner> TyKind<I> { - #[inline] - pub fn is_primitive(&self) -> bool { - matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_)) - } -} - // This is manually implemented because a derive would require `I: Debug` impl<I: Interner> fmt::Debug for TyKind<I> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 50d7bae21db..aeae866e9d3 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -465,6 +465,22 @@ impl Location { } } +/// Location of the statement at the given index for a given basic block. Assumes that `stmt_idx` +/// and `bb_idx` are valid for a given body. +pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location { + let bb = &body.blocks[*bb_idx]; + let stmt = &bb.statements[stmt_idx]; + Location(stmt.span) +} + +/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given +/// body. +pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location { + let bb = &body.blocks[*bb_idx]; + let terminator = &bb.terminator; + Location(terminator.span) +} + /// Reference to a place used to represent a partial projection. pub struct PlaceRef<'a> { pub local: Local, diff --git a/library/Cargo.lock b/library/Cargo.lock index aa22181a463..54ad052c523 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.121" +version = "0.1.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce956e6dc07082ec481f0935a51e83b343f8ca51be560452c0ebf830d0bdf5a5" +checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index a39a0a6ce0e..4365bcc4ad0 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.121", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index 0561f49c967..ae9608ec7bd 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -1,6 +1,3 @@ -// Disabling on android for the time being -// See https://github.com/rust-lang/rust/issues/73535#event-3477699747 -#![cfg(not(target_os = "android"))] // Disabling in Miri as these would take too long. #![cfg(not(miri))] #![feature(btree_extract_if)] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index caaf37f0465..38b1766c174 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -262,8 +262,6 @@ impl<T> Box<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::<u32>::new_uninit(); /// /// let five = unsafe { @@ -276,7 +274,7 @@ impl<T> Box<T> { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { @@ -292,7 +290,6 @@ impl<T> Box<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(new_zeroed_alloc)] /// /// let zero = Box::<u32>::new_zeroed(); @@ -350,7 +347,7 @@ impl<T> Box<T> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut five = Box::<u32>::try_new_uninit()?; /// @@ -380,7 +377,7 @@ impl<T> Box<T> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let zero = Box::<u32>::try_new_zeroed()?; /// let zero = unsafe { zero.assume_init() }; @@ -460,7 +457,7 @@ impl<T, A: Allocator> Box<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -498,7 +495,7 @@ impl<T, A: Allocator> Box<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -538,7 +535,7 @@ impl<T, A: Allocator> Box<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -576,7 +573,7 @@ impl<T, A: Allocator> Box<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -654,8 +651,6 @@ impl<T> Box<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -670,7 +665,7 @@ impl<T> Box<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> { unsafe { RawVec::with_capacity(len).into_box(len) } @@ -686,7 +681,6 @@ impl<T> Box<[T]> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// let values = Box::<[u32]>::new_zeroed_slice(3); /// let values = unsafe { values.assume_init() }; @@ -708,7 +702,7 @@ impl<T> Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let mut values = Box::<[u32]>::try_new_uninit_slice(3)?; /// let values = unsafe { @@ -746,7 +740,7 @@ impl<T> Box<[T]> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// let values = Box::<[u32]>::try_new_zeroed_slice(3)?; /// let values = unsafe { values.assume_init() }; @@ -778,7 +772,7 @@ impl<T, A: Allocator> Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -812,7 +806,7 @@ impl<T, A: Allocator> Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -837,7 +831,7 @@ impl<T, A: Allocator> Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -880,7 +874,7 @@ impl<T, A: Allocator> Box<[T], A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -927,8 +921,6 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut five = Box::<u32>::new_uninit(); /// /// let five: Box<u32> = unsafe { @@ -940,7 +932,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box<T, A> { let (raw, alloc) = Box::into_raw_with_allocator(self); @@ -958,7 +950,6 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> { /// /// ``` /// #![feature(box_uninit_write)] - /// #![feature(new_uninit)] /// /// let big_box = Box::<[usize; 1024]>::new_uninit(); /// @@ -1001,8 +992,6 @@ impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] - /// /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { @@ -1016,7 +1005,7 @@ impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 5e4b08df6cb..c459a8da820 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,7 +93,6 @@ // tidy-alphabetical-start #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] -#![cfg_attr(test, feature(new_uninit))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f153aa6d3be..1b31a78394e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -503,7 +503,6 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -518,7 +517,7 @@ impl<T> Rc<T> { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> { unsafe { @@ -540,7 +539,6 @@ impl<T> Rc<T> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::rc::Rc; /// @@ -594,7 +592,7 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -630,7 +628,7 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// @@ -692,7 +690,6 @@ impl<T, A: Allocator> Rc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -736,7 +733,6 @@ impl<T, A: Allocator> Rc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -799,7 +795,7 @@ impl<T, A: Allocator> Rc<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -843,7 +839,7 @@ impl<T, A: Allocator> Rc<T, A> { /// # Examples /// /// ``` - /// #![feature(allocator_api, new_uninit)] + /// #![feature(allocator_api)] /// /// use std::rc::Rc; /// use std::alloc::System; @@ -967,7 +963,6 @@ impl<T> Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -985,7 +980,7 @@ impl<T> Rc<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } @@ -1000,7 +995,6 @@ impl<T> Rc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; @@ -1035,7 +1029,6 @@ impl<T, A: Allocator> Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1072,7 +1065,6 @@ impl<T, A: Allocator> Rc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::rc::Rc; @@ -1122,7 +1114,6 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1136,7 +1127,7 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc<T, A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); @@ -1160,7 +1151,6 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::rc::Rc; @@ -1177,7 +1167,7 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4a3522f1a64..024a794f17b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -335,7 +335,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {} #[stable(feature = "arc_weak", since = "1.4.0")] -impl<T: ?Sized> fmt::Debug for Weak<T> { +impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(Weak)") } @@ -505,7 +505,6 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -521,7 +520,7 @@ impl<T> Arc<T> { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> { unsafe { @@ -543,7 +542,6 @@ impl<T> Arc<T> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::sync::Arc; /// @@ -614,7 +612,7 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -650,7 +648,7 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature( allocator_api)] /// /// use std::sync::Arc; /// @@ -711,7 +709,6 @@ impl<T, A: Allocator> Arc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -755,7 +752,6 @@ impl<T, A: Allocator> Arc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -845,7 +841,7 @@ impl<T, A: Allocator> Arc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -889,7 +885,7 @@ impl<T, A: Allocator> Arc<T, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit, allocator_api)] + /// #![feature(allocator_api)] /// /// use std::sync::Arc; /// use std::alloc::System; @@ -1101,7 +1097,6 @@ impl<T> Arc<[T]> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1120,7 +1115,7 @@ impl<T> Arc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } @@ -1136,7 +1131,6 @@ impl<T> Arc<[T]> { /// /// ``` /// #![feature(new_zeroed_alloc)] - /// #![feature(new_uninit)] /// /// use std::sync::Arc; /// @@ -1172,7 +1166,6 @@ impl<T, A: Allocator> Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// #![feature(allocator_api)] /// @@ -1208,7 +1201,6 @@ impl<T, A: Allocator> Arc<[T], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(allocator_api)] /// /// use std::sync::Arc; @@ -1257,7 +1249,6 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1271,7 +1262,7 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<T, A> { @@ -1296,7 +1287,6 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> { /// # Examples /// /// ``` - /// #![feature(new_uninit)] /// #![feature(get_mut_unchecked)] /// /// use std::sync::Arc; @@ -1313,7 +1303,7 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3d4add6fae4..c5c6a122cfe 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -15,7 +15,6 @@ #![feature(exact_size_is_empty)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] -#![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs index c5bc4185a36..dc03c4860e8 100644 --- a/library/alloc/tests/string.rs +++ b/library/alloc/tests/string.rs @@ -723,7 +723,6 @@ fn test_reserve_exact() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_with_capacity() { let string = String::try_with_capacity(1000).unwrap(); assert_eq!(0, string.len()); @@ -734,7 +733,6 @@ fn test_try_with_capacity() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve() { // These are the interesting cases: // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) @@ -803,7 +801,6 @@ fn test_try_reserve() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. // See that test for comments. diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index fd2ddbf59e4..3722fb06a6a 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1695,7 +1695,6 @@ fn test_reserve_exact() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_with_capacity() { let mut vec: Vec<u32> = Vec::try_with_capacity(5).unwrap(); assert_eq!(0, vec.len()); @@ -1707,7 +1706,6 @@ fn test_try_with_capacity() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve() { // These are the interesting cases: // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) @@ -1803,7 +1801,6 @@ fn test_try_reserve() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. // See that test for comments. diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index db972122fef..f32ba8d5aa4 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1185,7 +1185,6 @@ fn test_reserve_exact_2() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_with_capacity() { let vec: VecDeque<u32> = VecDeque::try_with_capacity(5).unwrap(); assert_eq!(0, vec.len()); @@ -1196,7 +1195,6 @@ fn test_try_with_capacity() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve() { // These are the interesting cases: // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) @@ -1292,7 +1290,6 @@ fn test_try_reserve() { #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. // See that test for comments. diff --git a/library/backtrace b/library/backtrace -Subproject 72265bea210891ae47bbe6d4f17b493ef060661 +Subproject 230570f2dac80a601f5c0b30da00cc9480bd35e diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index 32d15c386cb..3f1c58bbd72 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -8,6 +8,7 @@ #![feature(iter_array_chunks)] #![feature(iter_next_chunk)] #![feature(iter_advance_by)] +#![feature(isqrt)] extern crate test; diff --git a/library/core/benches/num/int_sqrt/mod.rs b/library/core/benches/num/int_sqrt/mod.rs new file mode 100644 index 00000000000..3c9d173e456 --- /dev/null +++ b/library/core/benches/num/int_sqrt/mod.rs @@ -0,0 +1,62 @@ +use rand::Rng; +use test::{black_box, Bencher}; + +macro_rules! int_sqrt_bench { + ($t:ty, $predictable:ident, $random:ident, $random_small:ident, $random_uniform:ident) => { + #[bench] + fn $predictable(bench: &mut Bencher) { + bench.iter(|| { + for n in 0..(<$t>::BITS / 8) { + for i in 1..=(100 as $t) { + let x = black_box(i << (n * 8)); + black_box(x.isqrt()); + } + } + }); + } + + #[bench] + fn $random(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the whole range of the type. */ + let numbers: Vec<$t> = + (0..256).map(|_| rng.gen::<$t>() >> rng.gen_range(0..<$t>::BITS)).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + + #[bench] + fn $random_small(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the range 0..256. */ + let numbers: Vec<$t> = + (0..256).map(|_| (rng.gen::<u8>() >> rng.gen_range(0..u8::BITS)) as $t).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + + #[bench] + fn $random_uniform(bench: &mut Bencher) { + let mut rng = crate::bench_rng(); + /* Exponentially distributed random numbers from the whole range of the type. */ + let numbers: Vec<$t> = (0..256).map(|_| rng.gen::<$t>()).collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).isqrt()); + } + }); + } + }; +} + +int_sqrt_bench! {u8, u8_sqrt_predictable, u8_sqrt_random, u8_sqrt_random_small, u8_sqrt_uniform} +int_sqrt_bench! {u16, u16_sqrt_predictable, u16_sqrt_random, u16_sqrt_random_small, u16_sqrt_uniform} +int_sqrt_bench! {u32, u32_sqrt_predictable, u32_sqrt_random, u32_sqrt_random_small, u32_sqrt_uniform} +int_sqrt_bench! {u64, u64_sqrt_predictable, u64_sqrt_random, u64_sqrt_random_small, u64_sqrt_uniform} +int_sqrt_bench! {u128, u128_sqrt_predictable, u128_sqrt_random, u128_sqrt_random_small, u128_sqrt_uniform} diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs index c1dc3a30622..7ff7443cfa7 100644 --- a/library/core/benches/num/mod.rs +++ b/library/core/benches/num/mod.rs @@ -2,6 +2,7 @@ mod dec2flt; mod flt2dec; mod int_log; mod int_pow; +mod int_sqrt; use std::str::FromStr; diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 65a4d537cc7..f29ac99b292 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -118,6 +118,10 @@ impl<'a> Argument<'a> { Self::new(x, Debug::fmt) } #[inline(always)] + pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> { + Self::new(x, |_, _| Ok(())) + } + #[inline(always)] pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> { Self::new(x, Octal::fmt) } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index bd99e90376a..8cb9accd59d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2949,7 +2949,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { /// sysroot which is built without ub_checks but with `#[rustc_preserve_ub_checks]`. /// For code that gets monomorphized in the user crate (i.e., generic functions and functions with /// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that -/// assertions are enabled whenever the *user crate* has UB checks enabled. However if the +/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] @@ -2957,7 +2957,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) { #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { - cfg!(debug_assertions) + cfg!(ub_checks) } /// Allocates a block of memory at compile time. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7f0efede240..06a745b690a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -203,6 +203,7 @@ #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] +#![feature(cfg_ub_checks)] #![feature(const_for)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7a9ca4011be..e602b497d17 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -19,7 +19,7 @@ pub use maybe_uninit::MaybeUninit; mod transmutability; #[unstable(feature = "transmutability", issue = "99571")] -pub use transmutability::{Assume, BikeshedIntrinsicFrom}; +pub use transmutability::{Assume, TransmuteFrom}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(inline)] diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 62d454a5289..049b32ede9c 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -11,10 +11,10 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; /// /// # Safety /// -/// If `Dst: BikeshedIntrinsicFrom<Src, ASSUMPTIONS>`, the compiler guarantees -/// that `Src` is soundly *union-transmutable* into a value of type `Dst`, -/// provided that the programmer has guaranteed that the given -/// [`ASSUMPTIONS`](Assume) are satisfied. +/// If `Dst: TransmuteFrom<Src, ASSUMPTIONS>`, the compiler guarantees that +/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided +/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume) +/// are satisfied. /// /// A union-transmute is any bit-reinterpretation conversion in the form of: /// @@ -47,7 +47,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(transmutability)] /// -/// use core::mem::{Assume, BikeshedIntrinsicFrom}; +/// use core::mem::{Assume, TransmuteFrom}; /// /// let src = 42u8; // size = 1 /// @@ -55,7 +55,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; /// struct Dst(u8); // size = 2 // /// let _ = unsafe { -/// <Dst as BikeshedIntrinsicFrom<u8, { Assume::SAFETY }>>::transmute(src) +/// <Dst as TransmuteFrom<u8, { Assume::SAFETY }>>::transmute(src) /// }; /// ``` /// @@ -87,7 +87,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; #[lang = "transmute_trait"] #[rustc_deny_explicit_impl(implement_via_object = false)] #[rustc_coinductive] -pub unsafe trait BikeshedIntrinsicFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> +pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, { @@ -140,23 +140,21 @@ where } } -/// Configurable proof assumptions of [`BikeshedIntrinsicFrom`]. +/// Configurable proof assumptions of [`TransmuteFrom`]. /// /// When `false`, the respective proof obligation belongs to the compiler. When /// `true`, the onus of the safety proof belongs to the programmer. -/// [`BikeshedIntrinsicFrom`]. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_opts"] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Assume { - /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for - /// transmutations that might violate the the alignment requirements of - /// references; e.g.: + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the the alignment requirements of references; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] /// #![feature(transmutability)] - /// use core::mem::{align_of, BikeshedIntrinsicFrom}; + /// use core::mem::{align_of, TransmuteFrom}; /// /// assert_eq!(align_of::<[u8; 2]>(), 1); /// assert_eq!(align_of::<u16>(), 2); @@ -165,18 +163,18 @@ pub struct Assume { /// /// // SAFETY: No safety obligations. /// let dst: &u16 = unsafe { - /// <_ as BikeshedIntrinsicFrom<_>>::transmute(src) + /// <_ as TransmuteFrom<_>>::transmute(src) /// }; /// ``` /// - /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured /// that references in the transmuted value satisfy the alignment /// requirements of their referent types; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(pointer_is_aligned_to, transmutability)] - /// use core::mem::{align_of, Assume, BikeshedIntrinsicFrom}; + /// use core::mem::{align_of, Assume, TransmuteFrom}; /// /// let src: &[u8; 2] = &[0xFF, 0xFF]; /// @@ -184,7 +182,7 @@ pub struct Assume { /// // SAFETY: We have checked above that the address of `src` satisfies the /// // alignment requirements of `u16`. /// Some(unsafe { - /// <_ as BikeshedIntrinsicFrom<_, { Assume::ALIGNMENT }>>::transmute(src) + /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src) /// }) /// } else { /// None @@ -194,21 +192,21 @@ pub struct Assume { /// ``` pub alignment: bool, - /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for - /// transmutations that extend the lifetimes of references. + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that extend the lifetimes of references. /// - /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured - /// that references in the transmuted value do not outlive their referents. + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that + /// references in the transmuted value do not outlive their referents. pub lifetimes: bool, - /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for - /// transmutations that might violate the library safety invariants of the - /// destination type; e.g.: + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the library safety invariants of the destination + /// type; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] /// #![feature(transmutability)] - /// use core::mem::BikeshedIntrinsicFrom; + /// use core::mem::TransmuteFrom; /// /// let src: u8 = 3; /// @@ -219,18 +217,18 @@ pub struct Assume { /// /// // SAFETY: No safety obligations. /// let dst: EvenU8 = unsafe { - /// <_ as BikeshedIntrinsicFrom<_>>::transmute(src) + /// <_ as TransmuteFrom<_>>::transmute(src) /// }; /// ``` /// - /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured /// that undefined behavior does not arise from using the transmuted value; /// e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(transmutability)] - /// use core::mem::{Assume, BikeshedIntrinsicFrom}; + /// use core::mem::{Assume, TransmuteFrom}; /// /// let src: u8 = 42; /// @@ -242,7 +240,7 @@ pub struct Assume { /// let maybe_dst: Option<EvenU8> = if src % 2 == 0 { /// // SAFETY: We have checked above that the value of `src` is even. /// Some(unsafe { - /// <_ as BikeshedIntrinsicFrom<_, { Assume::SAFETY }>>::transmute(src) + /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src) /// }) /// } else { /// None @@ -252,31 +250,31 @@ pub struct Assume { /// ``` pub safety: bool, - /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for - /// transmutations that might violate the language-level bit-validity - /// invariant of the destination type; e.g.: + /// When `false`, [`TransmuteFrom`] is not implemented for transmutations + /// that might violate the language-level bit-validity invariant of the + /// destination type; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] /// #![feature(transmutability)] - /// use core::mem::BikeshedIntrinsicFrom; + /// use core::mem::TransmuteFrom; /// /// let src: u8 = 3; /// /// // SAFETY: No safety obligations. /// let dst: bool = unsafe { - /// <_ as BikeshedIntrinsicFrom<_>>::transmute(src) + /// <_ as TransmuteFrom<_>>::transmute(src) /// }; /// ``` /// - /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured + /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured /// that the value being transmuted is a bit-valid instance of the /// transmuted value; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(transmutability)] - /// use core::mem::{Assume, BikeshedIntrinsicFrom}; + /// use core::mem::{Assume, TransmuteFrom}; /// /// let src: u8 = 1; /// @@ -284,7 +282,7 @@ pub struct Assume { /// // SAFETY: We have checked above that the value of `src` is a bit-valid /// // instance of `bool`. /// Some(unsafe { - /// <_ as BikeshedIntrinsicFrom<_, { Assume::VALIDITY }>>::transmute(src) + /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src) /// }) /// } else { /// None @@ -301,35 +299,34 @@ impl ConstParamTy_ for Assume {} impl UnsizedConstParamTy for Assume {} impl Assume { - /// With this, [`BikeshedIntrinsicFrom`] does not assume you have ensured - /// any safety obligations are met, and relies only upon its own analysis to - /// (dis)prove transmutability. + /// With this, [`TransmuteFrom`] does not assume you have ensured any safety + /// obligations are met, and relies only upon its own analysis to (dis)prove + /// transmutability. #[unstable(feature = "transmutability", issue = "99571")] pub const NOTHING: Self = Self { alignment: false, lifetimes: false, safety: false, validity: false }; - /// With this, [`BikeshedIntrinsicFrom`] assumes only that you have ensured - /// that references in the transmuted value satisfy the alignment - /// requirements of their referent types. See [`Assume::alignment`] for - /// examples. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value satisfy the alignment requirements of + /// their referent types. See [`Assume::alignment`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING }; - /// With this, [`BikeshedIntrinsicFrom`] assumes only that you have ensured - /// that references in the transmuted value do not outlive their referents. - /// See [`Assume::lifetimes`] for examples. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// references in the transmuted value do not outlive their referents. See + /// [`Assume::lifetimes`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING }; - /// With this, [`BikeshedIntrinsicFrom`] assumes only that you have ensured - /// that undefined behavior does not arise from using the transmuted value. - /// See [`Assume::safety`] for examples. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that + /// undefined behavior does not arise from using the transmuted value. See + /// [`Assume::safety`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING }; - /// With this, [`BikeshedIntrinsicFrom`] assumes only that you have ensured - /// that the value being transmuted is a bit-valid instance of the - /// transmuted value. See [`Assume::validity`] for examples. + /// With this, [`TransmuteFrom`] assumes only that you have ensured that the + /// value being transmuted is a bit-valid instance of the transmuted value. + /// See [`Assume::validity`] for examples. #[unstable(feature = "transmutability", issue = "99571")] pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING }; @@ -348,7 +345,7 @@ impl Assume { /// transmutability, /// )] /// #![allow(incomplete_features)] - /// use core::mem::{align_of, Assume, BikeshedIntrinsicFrom}; + /// use core::mem::{align_of, Assume, TransmuteFrom}; /// /// /// Attempts to transmute `src` to `&Dst`. /// /// @@ -360,7 +357,7 @@ impl Assume { /// /// alignment, are satisfied. /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst> /// where - /// &'a Dst: BikeshedIntrinsicFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>, + /// &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>, /// { /// if <*const _>::is_aligned_to(src, align_of::<Dst>()) { /// // SAFETY: By the above dynamic check, we have ensured that the address @@ -368,7 +365,7 @@ impl Assume { /// // on the caller, the safety obligations required by `ASSUME` have also /// // been satisfied. /// Some(unsafe { - /// <_ as BikeshedIntrinsicFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src) + /// <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src) /// }) /// } else { /// None diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 229cd89bea3..878a911dde5 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1641,7 +1641,33 @@ macro_rules! int_impl { if self < 0 { None } else { - Some((self as $UnsignedT).isqrt() as Self) + // SAFETY: Input is nonnegative in this `else` branch. + let result = unsafe { + crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT + }; + + // Inform the optimizer what the range of outputs is. If + // testing `core` crashes with no panic message and a + // `num::int_sqrt::i*` test failed, it's because your edits + // caused these assertions to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for + // nonnegative signed integers is bounded by + // `[0, <$ActualT>::MAX]`, sqrt(n) will be bounded by + // `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + // SAFETY: `<$ActualT>::MAX` is nonnegative. + const MAX_RESULT: $SelfT = unsafe { + crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT + }; + + crate::hint::assert_unchecked(result >= 0); + crate::hint::assert_unchecked(result <= MAX_RESULT); + } + + Some(result) } } @@ -2862,15 +2888,11 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] + #[track_caller] 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"), + None => crate::num::int_sqrt::panic_for_negative_argument(), } } @@ -2888,8 +2910,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2927,8 +2949,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and + /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -2943,6 +2965,11 @@ macro_rules! int_impl { /// assert_eq!(a.rem_euclid(-b), 3); /// assert_eq!((-a).rem_euclid(-b), 1); /// ``` + /// + /// This will panic: + /// ```should_panic + #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.rem_euclid(-1);")] + /// ``` #[doc(alias = "modulo", alias = "mod")] #[stable(feature = "euclidean_division", since = "1.38.0")] #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")] @@ -2971,8 +2998,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// @@ -3007,8 +3034,8 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is - /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag. + /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples /// diff --git a/library/core/src/num/int_sqrt.rs b/library/core/src/num/int_sqrt.rs new file mode 100644 index 00000000000..601e81f6993 --- /dev/null +++ b/library/core/src/num/int_sqrt.rs @@ -0,0 +1,316 @@ +//! These functions use the [Karatsuba square root algorithm][1] to compute the +//! [integer square root](https://en.wikipedia.org/wiki/Integer_square_root) +//! for the primitive integer types. +//! +//! The signed integer functions can only handle **nonnegative** inputs, so +//! that must be checked before calling those. +//! +//! [1]: <https://web.archive.org/web/20230511212802/https://inria.hal.science/inria-00072854v1/file/RR-3805.pdf> +//! "Paul Zimmermann. Karatsuba Square Root. \[Research Report\] RR-3805, +//! INRIA. 1999, pp.8. (inria-00072854)" + +/// This array stores the [integer square roots]( +/// https://en.wikipedia.org/wiki/Integer_square_root) and remainders of each +/// [`u8`](prim@u8) value. For example, `U8_ISQRT_WITH_REMAINDER[17]` will be +/// `(4, 1)` because the integer square root of 17 is 4 and because 17 is 1 +/// higher than 4 squared. +const U8_ISQRT_WITH_REMAINDER: [(u8, u8); 256] = { + let mut result = [(0, 0); 256]; + + let mut n: usize = 0; + let mut isqrt_n: usize = 0; + while n < result.len() { + result[n] = (isqrt_n as u8, (n - isqrt_n.pow(2)) as u8); + + n += 1; + if n == (isqrt_n + 1).pow(2) { + isqrt_n += 1; + } + } + + result +}; + +/// Returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any [`u8`](prim@u8) +/// input. +#[must_use = "this returns the result of the operation, \ + without modifying the original"] +#[inline] +pub const fn u8(n: u8) -> u8 { + U8_ISQRT_WITH_REMAINDER[n as usize].0 +} + +/// Generates an `i*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any **nonnegative** +/// input of a specific signed integer type. +macro_rules! signed_fn { + ($SignedT:ident, $UnsignedT:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + /// **nonnegative** + #[doc = concat!("[`", stringify!($SignedT), "`](prim@", stringify!($SignedT), ")")] + /// input. + /// + /// # Safety + /// + /// This results in undefined behavior when the input is negative. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn $SignedT(n: $SignedT) -> $SignedT { + debug_assert!(n >= 0, "Negative input inside `isqrt`."); + $UnsignedT(n as $UnsignedT) as $SignedT + } + }; +} + +signed_fn!(i8, u8); +signed_fn!(i16, u16); +signed_fn!(i32, u32); +signed_fn!(i64, u64); +signed_fn!(i128, u128); + +/// Generates a `u*` function that returns the [integer square root]( +/// https://en.wikipedia.org/wiki/Integer_square_root) of any input of +/// a specific unsigned integer type. +macro_rules! unsigned_fn { + ($UnsignedT:ident, $HalfBitsT:ident, $stages:ident) => { + /// Returns the [integer square root]( + /// https://en.wikipedia.org/wiki/Integer_square_root) of any + #[doc = concat!("[`", stringify!($UnsignedT), "`](prim@", stringify!($UnsignedT), ")")] + /// input. + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT { + if n <= <$HalfBitsT>::MAX as $UnsignedT { + $HalfBitsT(n as $HalfBitsT) as $UnsignedT + } else { + // The normalization shift satisfies the Karatsuba square root + // algorithm precondition "a₃ ≥ b/4" where a₃ is the most + // significant quarter of `n`'s bits and b is the number of + // values that can be represented by that quarter of the bits. + // + // b/4 would then be all 0s except the second most significant + // bit (010...0) in binary. Since a₃ must be at least b/4, a₃'s + // most significant bit or its neighbor must be a 1. Since a₃'s + // most significant bits are `n`'s most significant bits, the + // same applies to `n`. + // + // The reason to shift by an even number of bits is because an + // even number of bits produces the square root shifted to the + // left by half of the normalization shift: + // + // sqrt(n << (2 * p)) + // sqrt(2.pow(2 * p) * n) + // sqrt(2.pow(2 * p)) * sqrt(n) + // 2.pow(p) * sqrt(n) + // sqrt(n) << p + // + // Shifting by an odd number of bits leaves an ugly sqrt(2) + // multiplied in: + // + // sqrt(n << (2 * p + 1)) + // sqrt(2.pow(2 * p + 1) * n) + // sqrt(2 * 2.pow(2 * p) * n) + // sqrt(2) * sqrt(2.pow(2 * p)) * sqrt(n) + // sqrt(2) * 2.pow(p) * sqrt(n) + // sqrt(2) * (sqrt(n) << p) + const EVEN_MAKING_BITMASK: u32 = !1; + let normalization_shift = n.leading_zeros() & EVEN_MAKING_BITMASK; + n <<= normalization_shift; + + let s = $stages(n); + + let denormalization_shift = normalization_shift >> 1; + s >> denormalization_shift + } + } + }; +} + +/// Generates the first stage of the computation after normalization. +/// +/// # Safety +/// +/// `$n` must be nonzero. +macro_rules! first_stage { + ($original_bits:literal, $n:ident) => {{ + debug_assert!($n != 0, "`$n` is zero in `first_stage!`."); + + const N_SHIFT: u32 = $original_bits - 8; + let n = $n >> N_SHIFT; + + let (s, r) = U8_ISQRT_WITH_REMAINDER[n as usize]; + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then this stage puts the eight most-significant bits of `$n` into + // `n`. This means that `n` here has at least one 1 bit in its two + // most-significant bits, making `n` nonzero. + // + // `U8_ISQRT_WITH_REMAINDER[n as usize]` will give a nonzero `s` when + // given a nonzero `n`. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates a middle stage of the computation. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! middle_stage { + ($original_bits:literal, $ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `middle_stage!`."); + + const N_SHIFT: u32 = $original_bits - <$ty>::BITS; + let n = ($n >> N_SHIFT) as $ty; + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + const LOWEST_QUARTER_1_BITS: $ty = (1 << QUARTER_BITS) - 1; + + let lo = n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + let q = numerator / denominator; + let u = numerator % denominator; + + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (mut r, overflow) = + ((u << QUARTER_BITS) | (lo & LOWEST_QUARTER_1_BITS)).overflowing_sub(q * q); + if overflow { + r = r.wrapping_add(2 * s - 1); + s -= 1; + } + + // Inform the optimizer that `s` is nonzero. This will allow it to + // avoid generating code to handle division-by-zero panics in the next + // stage. + // + // SAFETY: If the original `$n` is zero, the top of the `unsigned_fn` + // macro recurses instead of continuing to this point, so the original + // `$n` wasn't a 0 if we've reached here. + // + // Then the `unsigned_fn` macro normalizes `$n` so that at least one of + // its two most-significant bits is a 1. + // + // Then these stages take as many of the most-significant bits of `$n` + // as will fit in this stage's type. For example, the stage that + // handles `u32` deals with the 32 most-significant bits of `$n`. This + // means that each stage has at least one 1 bit in `n`'s two + // most-significant bits, making `n` nonzero. + // + // Then this stage will produce the correct integer square root for + // that `n` value. Since `n` is nonzero, `s` will also be nonzero. + unsafe { crate::hint::assert_unchecked(s != 0) }; + (s, r) + }}; +} + +/// Generates the last stage of the computation before denormalization. +/// +/// # Safety +/// +/// `$s` must be nonzero. +macro_rules! last_stage { + ($ty:ty, $n:ident, $s:ident, $r:ident) => {{ + debug_assert!($s != 0, "`$s` is zero in `last_stage!`."); + + const HALF_BITS: u32 = <$ty>::BITS >> 1; + const QUARTER_BITS: u32 = <$ty>::BITS >> 2; + const LOWER_HALF_1_BITS: $ty = (1 << HALF_BITS) - 1; + + let lo = $n & LOWER_HALF_1_BITS; + let numerator = (($r as $ty) << QUARTER_BITS) | (lo >> QUARTER_BITS); + let denominator = ($s as $ty) << 1; + + let q = numerator / denominator; + let mut s = ($s << QUARTER_BITS) as $ty + q; + let (s_squared, overflow) = s.overflowing_mul(s); + if overflow || s_squared > $n { + s -= 1; + } + s + }}; +} + +/// Takes the normalized [`u16`](prim@u16) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u16_stages(n: u16) -> u16 { + let (s, r) = first_stage!(16, n); + last_stage!(u16, n, s, r) +} + +/// Takes the normalized [`u32`](prim@u32) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u32_stages(n: u32) -> u32 { + let (s, r) = first_stage!(32, n); + let (s, r) = middle_stage!(32, u16, n, s, r); + last_stage!(u32, n, s, r) +} + +/// Takes the normalized [`u64`](prim@u64) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u64_stages(n: u64) -> u64 { + let (s, r) = first_stage!(64, n); + let (s, r) = middle_stage!(64, u16, n, s, r); + let (s, r) = middle_stage!(64, u32, n, s, r); + last_stage!(u64, n, s, r) +} + +/// Takes the normalized [`u128`](prim@u128) input and gets its normalized +/// [integer square root](https://en.wikipedia.org/wiki/Integer_square_root). +/// +/// # Safety +/// +/// `n` must be nonzero. +#[inline] +const fn u128_stages(n: u128) -> u128 { + let (s, r) = first_stage!(128, n); + let (s, r) = middle_stage!(128, u16, n, s, r); + let (s, r) = middle_stage!(128, u32, n, s, r); + let (s, r) = middle_stage!(128, u64, n, s, r); + last_stage!(u128, n, s, r) +} + +unsigned_fn!(u16, u8, u16_stages); +unsigned_fn!(u32, u16, u32_stages); +unsigned_fn!(u64, u32, u64_stages); +unsigned_fn!(u128, u64, u128_stages); + +/// Instantiate this panic logic once, rather than for all the isqrt methods +/// on every single primitive type. +#[cold] +#[track_caller] +pub const fn panic_for_negative_argument() -> ! { + panic!("argument of integer square root cannot be negative") +} diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 309e1ba958a..e9e5324666a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -41,6 +41,7 @@ mod uint_macros; // import uint_impl! mod error; mod int_log10; +mod int_sqrt; mod nonzero; mod overflow_panic; mod saturating; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c6e9c249048..8b888f12da0 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -7,7 +7,7 @@ use crate::marker::{Freeze, StructuralPartialEq}; use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::str::FromStr; -use crate::{fmt, hint, intrinsics, ptr, ub_checks}; +use crate::{fmt, intrinsics, ptr, ub_checks}; /// A marker trait for primitive types which can be zero. /// @@ -1545,31 +1545,14 @@ macro_rules! nonzero_integer_signedness_dependent_methods { without modifying the original"] #[inline] pub const fn isqrt(self) -> Self { - // The algorithm is based on the one presented in - // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)> - // which cites as source the following C code: - // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>. - - let mut op = self.get(); - 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; - } + let result = self.get().isqrt(); - // SAFETY: The result fits in an integer with half as many bits. - // Inform the optimizer about it. - unsafe { hint::assert_unchecked(res < 1 << (Self::BITS / 2)) }; - - // SAFETY: The square root of an integer >= 1 is always >= 1. - unsafe { Self::new_unchecked(res) } + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never cause + // the output to decrease. Thus, since the input for nonzero + // unsigned integers has a lower bound of 1, the lower bound of the + // results will be sqrt(1), which is 1, so a result can't be zero. + unsafe { Self::new_unchecked(result) } } }; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0d0bbc5256f..d9036abecc5 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2762,10 +2762,24 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn isqrt(self) -> Self { - match NonZero::new(self) { - Some(x) => x.isqrt().get(), - None => 0, + let result = crate::num::int_sqrt::$ActualT(self as $ActualT) as $SelfT; + + // Inform the optimizer what the range of outputs is. If testing + // `core` crashes with no panic message and a `num::int_sqrt::u*` + // test failed, it's because your edits caused these assertions or + // the assertions in `fn isqrt` of `nonzero.rs` to become false. + // + // SAFETY: Integer square root is a monotonically nondecreasing + // function, which means that increasing the input will never + // cause the output to decrease. Thus, since the input for unsigned + // integers is bounded by `[0, <$ActualT>::MAX]`, sqrt(n) will be + // bounded by `[sqrt(0), sqrt(<$ActualT>::MAX)]`. + unsafe { + const MAX_RESULT: $SelfT = crate::num::int_sqrt::$ActualT(<$ActualT>::MAX) as $SelfT; + crate::hint::assert_unchecked(result <= MAX_RESULT); } + + result } /// Performs Euclidean division. diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 780e476f531..65f6bfb7ee1 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1370,7 +1370,15 @@ impl<Ptr: Deref> Pin<Ptr> { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&*self.__pointer) } } +} +// These methods being in a `Ptr: DerefMut` impl block concerns semver stability. +// Currently, calling e.g. `.set()` on a `Pin<&T>` sees that `Ptr: DerefMut` +// doesn't hold, and goes to check for a `.set()` method on `T`. But, if the +// `where Ptr: DerefMut` bound is moved to the method, rustc sees the impl block +// as a valid candidate, and doesn't go on to check other candidates when it +// sees that the bound on the method. +impl<Ptr: DerefMut> Pin<Ptr> { /// Gets a mutable reference to the pinned value this `Pin<Ptr>` points to. /// /// This is a generic method to go from `&mut Pin<Pointer<T>>` to `Pin<&mut T>`. @@ -1402,10 +1410,7 @@ impl<Ptr: Deref> Pin<Ptr> { /// ``` #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> - where - Ptr: DerefMut, - { + pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&mut *self.__pointer) } } @@ -1420,10 +1425,7 @@ impl<Ptr: Deref> Pin<Ptr> { #[unstable(feature = "pin_deref_mut", issue = "86918")] #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] - pub fn as_deref_mut(self: Pin<&mut Pin<Ptr>>) -> Pin<&mut Ptr::Target> - where - Ptr: DerefMut, - { + pub fn as_deref_mut(self: Pin<&mut Pin<Ptr>>) -> Pin<&mut Ptr::Target> { // SAFETY: What we're asserting here is that going from // // Pin<&mut Pin<Ptr>> @@ -1475,12 +1477,13 @@ impl<Ptr: Deref> Pin<Ptr> { #[inline(always)] pub fn set(&mut self, value: Ptr::Target) where - Ptr: DerefMut, Ptr::Target: Sized, { *(self.__pointer) = value; } +} +impl<Ptr: Deref> Pin<Ptr> { /// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`. /// /// # Safety diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs index 2320a7acc35..60902752dab 100644 --- a/library/core/tests/num/int_log.rs +++ b/library/core/tests/num/int_log.rs @@ -1,7 +1,4 @@ -//! This tests the `Integer::{ilog,log2,log10}` methods. These tests are in a -//! separate file because there's both a large number of them, and not all tests -//! can be run on Android. This is because in Android `ilog2` uses an imprecise -//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53 +//! Tests for the `Integer::{ilog,log2,log10}` methods. #[test] fn checked_ilog() { @@ -48,6 +45,10 @@ fn checked_ilog2() { assert_eq!(0i8.checked_ilog2(), None); assert_eq!(0i16.checked_ilog2(), None); + assert_eq!(8192u16.checked_ilog2(), Some((8192f32).log2() as u32)); + assert_eq!(32768u16.checked_ilog2(), Some((32768f32).log2() as u32)); + assert_eq!(8192i16.checked_ilog2(), Some((8192f32).log2() as u32)); + for i in 1..=u8::MAX { assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}"); } @@ -77,15 +78,6 @@ fn checked_ilog2() { } } -// Validate cases that fail on Android's imprecise float ilog2 implementation. -#[test] -#[cfg(not(target_os = "android"))] -fn checked_ilog2_not_android() { - assert_eq!(8192u16.checked_ilog2(), Some((8192f32).log2() as u32)); - assert_eq!(32768u16.checked_ilog2(), Some((32768f32).log2() as u32)); - assert_eq!(8192i16.checked_ilog2(), Some((8192f32).log2() as u32)); -} - #[test] fn checked_ilog10() { assert_eq!(0u8.checked_ilog10(), None); diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 7cd3b54e3f3..830a96204ca 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -289,38 +289,6 @@ macro_rules! int_module { } #[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; let b = 3; diff --git a/library/core/tests/num/int_sqrt.rs b/library/core/tests/num/int_sqrt.rs new file mode 100644 index 00000000000..d68db0787d2 --- /dev/null +++ b/library/core/tests/num/int_sqrt.rs @@ -0,0 +1,248 @@ +macro_rules! tests { + ($isqrt_consistency_check_fn_macro:ident : $($T:ident)+) => { + $( + mod $T { + $isqrt_consistency_check_fn_macro!($T); + + // Check that the following produce the correct values from + // `isqrt`: + // + // * the first and last 128 nonnegative values + // * powers of two, minus one + // * powers of two + // + // For signed types, check that `checked_isqrt` and `isqrt` + // either produce the same numeric value or respectively + // produce `None` and a panic. Make sure to do a consistency + // check for `<$T>::MIN` as well, as no nonnegative values + // negate to it. + // + // For unsigned types check that `isqrt` produces the same + // numeric value for `$T` and `NonZero<$T>`. + #[test] + fn isqrt() { + isqrt_consistency_check(<$T>::MIN); + + for n in (0..=127) + .chain(<$T>::MAX - 127..=<$T>::MAX) + .chain((0..<$T>::MAX.count_ones()).map(|exponent| (1 << exponent) - 1)) + .chain((0..<$T>::MAX.count_ones()).map(|exponent| 1 << exponent)) + { + isqrt_consistency_check(n); + + let isqrt_n = n.isqrt(); + assert!( + isqrt_n + .checked_mul(isqrt_n) + .map(|isqrt_n_squared| isqrt_n_squared <= n) + .unwrap_or(false), + "`{n}.isqrt()` should be lower than {isqrt_n}." + ); + assert!( + (isqrt_n + 1) + .checked_mul(isqrt_n + 1) + .map(|isqrt_n_plus_1_squared| n < isqrt_n_plus_1_squared) + .unwrap_or(true), + "`{n}.isqrt()` should be higher than {isqrt_n})." + ); + } + } + + // Check the square roots of: + // + // * the first 1,024 perfect squares + // * halfway between each of the first 1,024 perfect squares + // and the next perfect square + // * the next perfect square after the each of the first 1,024 + // perfect squares, minus one + // * the last 1,024 perfect squares + // * the last 1,024 perfect squares, minus one + // * halfway between each of the last 1,024 perfect squares + // and the previous perfect square + #[test] + // Skip this test on Miri, as it takes too long to run. + #[cfg(not(miri))] + fn isqrt_extended() { + // The correct value is worked out by using the fact that + // the nth nonzero perfect square is the sum of the first n + // odd numbers: + // + // 1 = 1 + // 4 = 1 + 3 + // 9 = 1 + 3 + 5 + // 16 = 1 + 3 + 5 + 7 + // + // Note also that the last odd number added in is two times + // the square root of the previous perfect square, plus + // one: + // + // 1 = 2*0 + 1 + // 3 = 2*1 + 1 + // 5 = 2*2 + 1 + // 7 = 2*3 + 1 + // + // That means we can add the square root of this perfect + // square once to get about halfway to the next perfect + // square, then we can add the square root of this perfect + // square again to get to the next perfect square, minus + // one, then we can add one to get to the next perfect + // square. + // + // This allows us to, for each of the first 1,024 perfect + // squares, test that the square roots of the following are + // all correct and equal to each other: + // + // * the current perfect square + // * about halfway to the next perfect square + // * the next perfect square, minus one + let mut n: $T = 0; + for sqrt_n in 0..1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T { + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`{sqrt_n}.pow(2).isqrt()` should be {sqrt_n}." + ); + + n += sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n += sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n += 1; + } + + // Similarly, for each of the last 1,024 perfect squares, + // check: + // + // * the current perfect square + // * the current perfect square, minus one + // * about halfway to the previous perfect square + // + // `MAX`'s `isqrt` return value is verified in the `isqrt` + // test function above. + let maximum_sqrt = <$T>::MAX.isqrt(); + let mut n = maximum_sqrt * maximum_sqrt; + + for sqrt_n in (maximum_sqrt - 1_024.min((1_u128 << (<$T>::MAX.count_ones()/2)) - 1) as $T..maximum_sqrt).rev() { + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n + 1, + "`{0}.pow(2).isqrt()` should be {0}.", + sqrt_n + 1 + ); + + n -= 1; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "`({}.pow(2) - 1).isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n -= sqrt_n; + isqrt_consistency_check(n); + assert_eq!( + n.isqrt(), + sqrt_n, + "{n} is about halfway between `{sqrt_n}.pow(2)` and `{}.pow(2)`, so `{n}.isqrt()` should be {sqrt_n}.", + sqrt_n + 1 + ); + + n -= sqrt_n; + } + } + } + )* + }; +} + +macro_rules! signed_check { + ($T:ident) => { + /// This takes an input and, if it's nonnegative or + #[doc = concat!("`", stringify!($T), "::MIN`,")] + /// checks that `isqrt` and `checked_isqrt` produce equivalent results + /// for that input and for the negative of that input. + /// + /// # Note + /// + /// This cannot check that negative inputs to `isqrt` cause panics if + /// panics abort instead of unwind. + fn isqrt_consistency_check(n: $T) { + // `<$T>::MIN` will be negative, so ignore it in this nonnegative + // section. + if n >= 0 { + assert_eq!( + Some(n.isqrt()), + n.checked_isqrt(), + "`{n}.checked_isqrt()` should match `Some({n}.isqrt())`.", + ); + } + + // `wrapping_neg` so that `<$T>::MIN` will negate to itself rather + // than panicking. + let negative_n = n.wrapping_neg(); + + // Zero negated will still be nonnegative, so ignore it in this + // negative section. + if negative_n < 0 { + assert_eq!( + negative_n.checked_isqrt(), + None, + "`({negative_n}).checked_isqrt()` should be `None`, as {negative_n} is negative.", + ); + + // `catch_unwind` only works when panics unwind rather than abort. + #[cfg(panic = "unwind")] + { + std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| (-n).isqrt())).expect_err( + &format!("`({negative_n}).isqrt()` should have panicked, as {negative_n} is negative.") + ); + } + } + } + }; +} + +macro_rules! unsigned_check { + ($T:ident) => { + /// This takes an input and, if it's nonzero, checks that `isqrt` + /// produces the same numeric value for both + #[doc = concat!("`", stringify!($T), "` and ")] + #[doc = concat!("`NonZero<", stringify!($T), ">`.")] + fn isqrt_consistency_check(n: $T) { + // Zero cannot be turned into a `NonZero` value, so ignore it in + // this nonzero section. + if n > 0 { + assert_eq!( + n.isqrt(), + core::num::NonZero::<$T>::new(n) + .expect( + "Was not able to create a new `NonZero` value from a nonzero number." + ) + .isqrt() + .get(), + "`{n}.isqrt` should match `NonZero`'s `{n}.isqrt().get()`.", + ); + } + } + }; +} + +tests!(signed_check: i8 i16 i32 i64 i128); +tests!(unsigned_check: u8 u16 u32 u64 u128); diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index dad46ad88fe..b14fe0b22c3 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -27,6 +27,7 @@ mod const_from; mod dec2flt; mod flt2dec; mod int_log; +mod int_sqrt; mod ops; mod wrapping; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index c271ac18706..72b53c60f74 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,7 +28,6 @@ #![feature(decl_macro)] #![feature(maybe_uninit_write_slice)] #![feature(negative_impls)] -#![feature(new_uninit)] #![feature(panic_can_unwind)] #![feature(restricted_std)] #![feature(rustc_attrs)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 334c75df231..5f0144922ca 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.121" } +compiler_builtins = { version = "0.1.123" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 506d708d0d2..b436fe9929c 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -250,9 +250,14 @@ impl f128 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 033a3d45009..b2cd5fae9d0 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -249,9 +249,14 @@ impl f16 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 35c2a77b533..cafbe9761da 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -228,9 +228,14 @@ impl f32 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index c177f74a97e..fba283e3a44 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -228,9 +228,14 @@ impl f64 { /// /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`. /// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is - /// returned. Note, however, that conserving the sign bit on NaN across arithmetical operations - /// is not generally guaranteed. See [specification of NaN bit - /// patterns](primitive@f32#nan-bit-patterns) for more info. + /// returned. + /// + /// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note + /// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust + /// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the + /// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable + /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more + /// info. /// /// # Examples /// diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 0b12e5777c8..cf226bd28d0 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -94,7 +94,9 @@ impl<R: Read> BufReader<R> { pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> { BufReader { inner, buf: Buffer::with_capacity(capacity) } } +} +impl<R: Read + ?Sized> BufReader<R> { /// Attempt to look ahead `n` bytes. /// /// `n` must be less than `capacity`. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f65e9bc8d8b..bea8eda2619 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -362,7 +362,6 @@ #![feature(allocator_api)] #![feature(get_mut_unchecked)] #![feature(map_try_insert)] -#![feature(new_uninit)] #![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] #![feature(thin_box)] diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 2f5d75dc4bc..b888eb7d95c 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -109,19 +109,15 @@ if #[cfg(not(target_vendor = "uwp"))] { } // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. -cfg_if::cfg_if! { -if #[cfg(not(target_vendor = "win7"))] { - #[cfg(target_arch = "x86")] - #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } - #[cfg(not(target_arch = "x86"))] - #[link(name = "bcryptprimitives", kind = "raw-dylib")] - extern "system" { - pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; - } -}} +#[cfg(not(target_vendor = "win7"))] +#[cfg_attr( + target_arch = "x86", + link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated") +)] +#[cfg_attr(not(target_arch = "x86"), link(name = "bcryptprimitives", kind = "raw-dylib"))] +extern "system" { + pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL; +} // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 69486705656..dcd5cd7f6b9 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -5,6 +5,10 @@ feature(stdarch_arm_feature_detection) )] #![cfg_attr( + all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), + feature(stdarch_aarch64_feature_detection) +)] +#![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) )] @@ -36,21 +40,34 @@ fn aarch64_linux() { println!("bf16: {}", is_aarch64_feature_detected!("bf16")); println!("bti: {}", is_aarch64_feature_detected!("bti")); println!("crc: {}", is_aarch64_feature_detected!("crc")); + println!("cssc: {}", is_aarch64_feature_detected!("cssc")); println!("dit: {}", is_aarch64_feature_detected!("dit")); println!("dotprod: {}", is_aarch64_feature_detected!("dotprod")); println!("dpb2: {}", is_aarch64_feature_detected!("dpb2")); println!("dpb: {}", is_aarch64_feature_detected!("dpb")); + println!("ecv: {}", is_aarch64_feature_detected!("ecv")); println!("f32mm: {}", is_aarch64_feature_detected!("f32mm")); println!("f64mm: {}", is_aarch64_feature_detected!("f64mm")); + println!("faminmax: {}", is_aarch64_feature_detected!("faminmax")); println!("fcma: {}", is_aarch64_feature_detected!("fcma")); println!("fhm: {}", is_aarch64_feature_detected!("fhm")); + println!("flagm2: {}", is_aarch64_feature_detected!("flagm2")); println!("flagm: {}", is_aarch64_feature_detected!("flagm")); println!("fp16: {}", is_aarch64_feature_detected!("fp16")); + println!("fp8: {}", is_aarch64_feature_detected!("fp8")); + println!("fp8dot2: {}", is_aarch64_feature_detected!("fp8dot2")); + println!("fp8dot4: {}", is_aarch64_feature_detected!("fp8dot4")); + println!("fp8fma: {}", is_aarch64_feature_detected!("fp8fma")); + println!("fpmr: {}", is_aarch64_feature_detected!("fpmr")); println!("frintts: {}", is_aarch64_feature_detected!("frintts")); + println!("hbc: {}", is_aarch64_feature_detected!("hbc")); println!("i8mm: {}", is_aarch64_feature_detected!("i8mm")); println!("jsconv: {}", is_aarch64_feature_detected!("jsconv")); + println!("lse128: {}", is_aarch64_feature_detected!("lse128")); println!("lse2: {}", is_aarch64_feature_detected!("lse2")); println!("lse: {}", is_aarch64_feature_detected!("lse")); + println!("lut: {}", is_aarch64_feature_detected!("lut")); + println!("mops: {}", is_aarch64_feature_detected!("mops")); println!("mte: {}", is_aarch64_feature_detected!("mte")); println!("neon: {}", is_aarch64_feature_detected!("neon")); println!("paca: {}", is_aarch64_feature_detected!("paca")); @@ -58,20 +75,37 @@ fn aarch64_linux() { println!("pmull: {}", is_aarch64_feature_detected!("pmull")); println!("rand: {}", is_aarch64_feature_detected!("rand")); println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2")); + println!("rcpc3: {}", is_aarch64_feature_detected!("rcpc3")); println!("rcpc: {}", is_aarch64_feature_detected!("rcpc")); println!("rdm: {}", is_aarch64_feature_detected!("rdm")); println!("sb: {}", is_aarch64_feature_detected!("sb")); println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); + println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); + println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); + println!("sme-f8f32: {}", is_aarch64_feature_detected!("sme-f8f32")); + println!("sme-fa64: {}", is_aarch64_feature_detected!("sme-fa64")); + println!("sme-i16i64: {}", is_aarch64_feature_detected!("sme-i16i64")); + println!("sme-lutv2: {}", is_aarch64_feature_detected!("sme-lutv2")); + println!("sme2: {}", is_aarch64_feature_detected!("sme2")); + println!("sme2p1: {}", is_aarch64_feature_detected!("sme2p1")); + println!("sme: {}", is_aarch64_feature_detected!("sme")); println!("ssbs: {}", is_aarch64_feature_detected!("ssbs")); + println!("ssve-fp8dot2: {}", is_aarch64_feature_detected!("ssve-fp8dot2")); + println!("ssve-fp8dot4: {}", is_aarch64_feature_detected!("ssve-fp8dot4")); + println!("ssve-fp8fma: {}", is_aarch64_feature_detected!("ssve-fp8fma")); + println!("sve-b16b16: {}", is_aarch64_feature_detected!("sve-b16b16")); println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes")); println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm")); println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3")); println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4")); println!("sve2: {}", is_aarch64_feature_detected!("sve2")); + println!("sve2p1: {}", is_aarch64_feature_detected!("sve2p1")); println!("sve: {}", is_aarch64_feature_detected!("sve")); println!("tme: {}", is_aarch64_feature_detected!("tme")); + println!("wfxt: {}", is_aarch64_feature_detected!("wfxt")); // tidy-alphabetical-end } diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 4ee9fbc3142..a2bb03cd5ac 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -313,7 +313,7 @@ lint_any!( RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; Rls, "src/tools/rls", "rls"; RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - Rustdoc, "src/tools/rustdoc", "clippy"; + Rustdoc, "src/librustdoc", "clippy"; Rustfmt, "src/tools/rustfmt", "rustfmt"; RustInstaller, "src/tools/rust-installer", "rust-installer"; Tidy, "src/tools/tidy", "tidy"; diff --git a/src/ci/scripts/dump-environment.sh b/src/ci/scripts/dump-environment.sh index 812690181e9..7afaa472f6e 100755 --- a/src/ci/scripts/dump-environment.sh +++ b/src/ci/scripts/dump-environment.sh @@ -15,9 +15,7 @@ df -h echo echo "biggest files in the working dir:" -set +o pipefail -du . | sort -nr | head -n100 -set -o pipefail +du . | sort -n | tail -n100 | sort -nr # because piping sort to head gives a broken pipe echo if isMacOS diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh index 569c4a4136d..d635d438472 100755 --- a/src/ci/scripts/select-xcode.sh +++ b/src/ci/scripts/select-xcode.sh @@ -1,5 +1,6 @@ #!/bin/bash # This script selects the Xcode instance to use. +# It also tries to do some cleanup in CI jobs of unused Xcodes. set -euo pipefail IFS=$'\n\t' @@ -7,5 +8,21 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isMacOS; then + # This additional step is to try to remove an Xcode we aren't using because each one is HUGE + old_xcode="$(xcode-select --print-path)" + old_xcode="${old_xcode%/*}" # pop a dir + old_xcode="${old_xcode%/*}" # twice + if [[ $old_xcode =~ $SELECT_XCODE ]]; then + echo "xcode-select.sh's brutal hack may not be necessary?" + exit 1 + elif [[ $SELECT_XCODE =~ "16" ]]; then + echo "Using Xcode 16? Please fix xcode-select.sh" + exit 1 + fi + if [ $CI ]; then # just in case someone sources this on their real computer + sudo rm -rf "${old_xcode}" + xcode_16="${old_xcode%/*}/Xcode-16.0.0.app" + sudo rm -rf "${xcode_16}" + fi sudo xcode-select -s "${SELECT_XCODE}" fi diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index c9c85ec20b4..61c187fa77c 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -19,18 +19,18 @@ fi if [[ "${DEPLOY-0}" -eq "1" ]] || [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then dist_dir="${build_dir}/dist" rm -rf "${dist_dir}/doc" - cp -r "${dist_dir}"/* "${upload_dir}" + mv "${dist_dir}"/* "${upload_dir}" fi # CPU usage statistics. -cp build/cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" +mv build/cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" # Build metrics generated by x.py. -cp "${build_dir}/metrics.json" "${upload_dir}/metrics-${CI_JOB_NAME}.json" +mv "${build_dir}/metrics.json" "${upload_dir}/metrics-${CI_JOB_NAME}.json" # Toolstate data. if [[ -n "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then - cp /tmp/toolstate/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" + mv /tmp/toolstate/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" fi echo "Files that will be uploaded:" @@ -55,7 +55,7 @@ then echo "# CI artifacts" >> "${GITHUB_STEP_SUMMARY}" for filename in "${upload_dir}"/*.xz; do - filename=`basename "${filename}"` + filename=$(basename "${filename}") echo "- [${filename}](${access_url}/${filename})" >> "${GITHUB_STEP_SUMMARY}" done fi diff --git a/src/doc/book b/src/doc/book -Subproject 04bc1396bb857f35b5dda1d773c9571e1f25330 +Subproject e7d217be2a75ef1753f0988d6ccaba4d7e37625 diff --git a/src/doc/edition-guide b/src/doc/edition-guide -Subproject aeeb287d41a0332c210da122bea8e0e91844ab3 +Subproject eeba2cb9c37ab74118a4fb5e5233f7397e4a91f diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject 019f3928d8b939ec71b63722dcc2e4633015644 +Subproject ff5d61d56f11e1986bfa9652c6aff7731576c37 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject 6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e +Subproject 14649f15d232d509478206ee9ed5105641aa60d diff --git a/src/doc/reference b/src/doc/reference -Subproject 62cd0df95061ba0ac886333f5cd7f3012f149da +Subproject 0668397076da350c404dadcf07b6cbc433ad374 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 8f94061936e492159f4f6c09c0f917a7521893f +Subproject 859786c5bc99301bbc22fc631a5c2b341860da0 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 43d83780db545a1ed6d45773312fc578987e396 +Subproject fa928a6d19e1666d8d811dfe3fd35cdad3b4e45 diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md index dfc4871b924..992f14a79bf 100644 --- a/src/doc/rustc/src/check-cfg.md +++ b/src/doc/rustc/src/check-cfg.md @@ -99,7 +99,7 @@ the need to specify them manually. Well known names and values are implicitly added as long as at least one `--check-cfg` argument is present. -As of `2024-05-06T`, the list of known names is as follows: +As of `2024-08-20T`, the list of known names is as follows: <!--- See CheckCfg::fill_well_known in compiler/rustc_session/src/config.rs --> @@ -107,6 +107,7 @@ As of `2024-05-06T`, the list of known names is as follows: - `debug_assertions` - `doc` - `doctest` + - `fmt_debug` - `miri` - `overflow_checks` - `panic` diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index fa23e3e414d..e5631ba4274 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -47,7 +47,7 @@ KIND=PATH` where `KIND` may be one of: directory. - `native` — Only search for native libraries in this directory. - `framework` — Only search for macOS frameworks in this directory. -- `all` — Search for all library kinds in this directory. This is the default +- `all` — Search for all library kinds in this directory, except frameworks. This is the default if `KIND` is not specified. <a id="option-l-link-lib"></a> diff --git a/src/doc/unstable-book/src/compiler-flags/fmt-debug.md b/src/doc/unstable-book/src/compiler-flags/fmt-debug.md new file mode 100644 index 00000000000..bb8663dceae --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/fmt-debug.md @@ -0,0 +1,15 @@ +# `fmt-debug` + +The tracking issue for this feature is: [#129709](https://github.com/rust-lang/rust/issues/129709). + +------------------------ + +Option `-Z fmt-debug=val` controls verbosity of derived `Debug` implementations +and debug formatting in format strings (`{:?}`). + +* `full` — `#[derive(Debug)]` prints types recursively. This is the default behavior. + +* `shallow` — `#[derive(Debug)]` prints only the type name, or name of a variant of a fieldless enums. Details of the `Debug` implementation are not stable and may change in the future. Behavior of custom `fmt::Debug` implementations is not affected. + +* `none` — `#[derive(Debug)]` does not print anything at all. `{:?}` in formatting strings has no effect. + This option may reduce size of binaries, and remove occurrences of type names in the binary that are not removed by striping symbols. However, it may also cause `panic!` and `assert!` messages to be incomplete. diff --git a/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md b/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md new file mode 100644 index 00000000000..7b99c25a694 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/lint-llvm-ir.md @@ -0,0 +1,7 @@ +# `lint-llvm-ir` + +--------------------- + +This flag will add `LintPass` to the start of the pipeline. +You can use it to check for common errors in the LLVM IR generated by `rustc`. +You can add `-Cllvm-args=-lint-abort-on-error` to abort the process if errors were found. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index edc63a25ac1..24940f0d6fb 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -775,22 +775,47 @@ See the [Clang SafeStack documentation][clang-safestack] for more details. # ShadowCallStack -ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack. - -ShadowCallStack requires a platform ABI which reserves `x18` as the instrumentation makes use of this register. +ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' +and loading the return address from that shadow call stack. +AArch64 and RISC-V both have a platform register defined in their ABIs, which is `x18` and `x3`/`gp` respectively, that can optionally be reserved for this purpose. +Software support from the operating system and runtime may be required depending on the target platform which is detailed in the remaining section. +See the [Clang ShadowCallStack documentation][clang-scs] for more details. ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and is supported on the following targets: -* `aarch64-linux-android` +## AArch64 family -A runtime must be provided by the application or operating system. +ShadowCallStack requires the use of the ABI defined platform register, `x18`, which is required for code generation purposes. +When `x18` is not reserved, and is instead used as a scratch register subsequently, enabling ShadowCallStack would lead to undefined behaviour +due to corruption of return address or invalid memory access when the instrumentation restores return register to the link register `lr` from the +already clobbered `x18` register. +In other words, code that is calling into or called by functions instrumented with ShadowCallStack must reserve the `x18` register or preserve its value. -See the [Clang ShadowCallStack documentation][clang-scs] for more details. +### `aarch64-linux-android` and `aarch64-unknown-fuchsia`/`aarch64-fuchsia` -* `aarch64-unknown-none` +This target already reserves the `x18` register. +A runtime must be provided by the application or operating system. +If `bionic` is used on this target, the software support is provided. +Otherwise, a runtime needs to prepare a memory region and points `x18` to the region which serves as the shadow call stack. + +### `aarch64-unknown-none` In addition to support from a runtime by the application or operating system, the `-Zfixed-x18` flag is also mandatory. +## RISC-V 64 family + +ShadowCallStack uses either the `gp` register for software shadow stack, also known as `x3`, or the `ssp` register if [`Zicfiss`][riscv-zicfiss] extension is available. +`gp`/`x3` is currently always reserved and available for ShadowCallStack instrumentation, and `ssp` in case of `Zicfiss` is only accessible through its dedicated shadow stack instructions. + +Support from the runtime and operating system is required when `gp`/`x3` is used for software shadow stack. +A runtime must prepare a memory region and point `gp`/`x3` to the region before executing the code. + +The following targets support ShadowCallStack. + +* `riscv64imac-unknown-none-elf` +* `riscv64gc-unknown-none-elf` +* `riscv64gc-unknown-fuchsia` + # ThreadSanitizer ThreadSanitizer is a data race detection tool. It is supported on the following @@ -912,3 +937,4 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html [linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html [llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html +[riscv-zicfiss]: https://github.com/riscv/riscv-cfi/blob/3f8e450c481ac303bd5643444f7a89672f24476e/src/cfi_backward.adoc diff --git a/src/doc/unstable-book/src/language-features/struct-target-features.md b/src/doc/unstable-book/src/language-features/struct-target-features.md new file mode 100644 index 00000000000..e814fe90072 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/struct-target-features.md @@ -0,0 +1,7 @@ +# `struct_target_features` + +The tracking issue for this feature is: [#129107] + +[#129107]: https://github.com/rust-lang/rust/issues/129107 + +------------------------ diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index f46ffea830e..577b10a31ae 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -341,7 +341,7 @@ fn clean_region_outlives_constraints<'tcx>( .map(|®ion| { let lifetime = early_bound_region_name(region) .inspect(|name| assert!(region_params.contains(name))) - .map(|name| Lifetime(name)) + .map(Lifetime) .unwrap_or(Lifetime::statik()); clean::GenericBound::Outlives(lifetime) }) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 48c3fb65203..96e7f5c61c3 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -24,7 +24,7 @@ pub(crate) fn synthesize_blanket_impls( let mut blanket_impls = Vec::new(); for trait_def_id in tcx.all_traits() { if !cx.cache.effective_visibilities.is_reachable(tcx, trait_def_id) - || cx.generated_synthetics.get(&(ty.skip_binder(), trait_def_id)).is_some() + || cx.generated_synthetics.contains(&(ty.skip_binder(), trait_def_id)) { continue; } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index f8953f0ebcf..962a5a05737 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -54,7 +54,7 @@ pub(crate) fn try_inline( debug!("attrs={attrs:?}"); let attrs_without_docs = attrs.map(|(attrs, def_id)| { - (attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id) + (attrs.iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id) }); let attrs_without_docs = attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id)); @@ -288,10 +288,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds } } -pub(crate) fn build_function<'tcx>( - cx: &mut DocContext<'tcx>, - def_id: DefId, -) -> Box<clean::Function> { +pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> { let sig = cx.tcx.fn_sig(def_id).instantiate_identity(); // The generics need to be cleaned before the signature. let mut generics = @@ -425,7 +422,7 @@ pub(crate) fn merge_attrs( both.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } else { - (Attributes::from_ast(&old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg)) + (Attributes::from_ast(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg)) } } @@ -791,16 +788,15 @@ fn build_macro( /// implementation for `AssociatedType` fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { for pred in &mut g.where_predicates { - match *pred { - clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => { - bounds.retain(|bound| match bound { - clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { - trait_.def_id() != trait_did - } - _ => true, - }); - } - _ => {} + if let clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } = + *pred + { + bounds.retain(|bound| match bound { + clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { + trait_.def_id() != trait_did + } + _ => true, + }); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5260e363dd6..3cb02f379e4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -266,7 +266,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>( ) } -fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime { +fn clean_lifetime(lifetime: &hir::Lifetime, cx: &mut DocContext<'_>) -> Lifetime { if let Some( rbv::ResolvedArg::EarlyBound(did) | rbv::ResolvedArg::LateBound(_, _, did) @@ -274,7 +274,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> ) = cx.tcx.named_bound_var(lifetime.hir_id) && let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt()) { - return lt.clone(); + return *lt; } Lifetime(lifetime.ident.name) } @@ -285,7 +285,7 @@ pub(crate) fn clean_const<'tcx>( ) -> ConstantKind { match &constant.kind { hir::ConstArgKind::Path(qpath) => { - ConstantKind::Path { path: qpath_to_string(&qpath).into() } + ConstantKind::Path { path: qpath_to_string(qpath).into() } } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, } @@ -299,7 +299,7 @@ pub(crate) fn clean_middle_const<'tcx>( ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } } -pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> { +pub(crate) fn clean_middle_region(region: ty::Region<'_>) -> Option<Lifetime> { match *region { ty::ReStatic => Some(Lifetime::statik()), _ if !region.has_name() => None, @@ -389,8 +389,8 @@ fn clean_poly_trait_predicate<'tcx>( }) } -fn clean_region_outlives_predicate<'tcx>( - pred: ty::RegionOutlivesPredicate<'tcx>, +fn clean_region_outlives_predicate( + pred: ty::RegionOutlivesPredicate<'_>, ) -> Option<WherePredicate> { let ty::OutlivesPredicate(a, b) = pred; @@ -513,10 +513,10 @@ fn projection_to_path_segment<'tcx>( } } -fn clean_generic_param_def<'tcx>( +fn clean_generic_param_def( def: &ty::GenericParamDef, defaults: ParamDefaults, - cx: &mut DocContext<'tcx>, + cx: &mut DocContext<'_>, ) -> GenericParamDef { let (name, kind) = match def.kind { ty::GenericParamDefKind::Lifetime => { @@ -1303,10 +1303,7 @@ pub(crate) fn clean_impl_item<'tcx>( }) } -pub(crate) fn clean_middle_assoc_item<'tcx>( - assoc_item: &ty::AssocItem, - cx: &mut DocContext<'tcx>, -) -> Item { +pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocContext<'_>) -> Item { let tcx = cx.tcx; let kind = match assoc_item.kind { ty::AssocKind::Const => { @@ -1459,7 +1456,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( // which only has one associated type, which is not a GAT, so whatever. } } - bounds.extend(mem::replace(pred_bounds, Vec::new())); + bounds.extend(mem::take(pred_bounds)); false } _ => true, @@ -1661,7 +1658,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type expanded } else { // First we check if it's a private re-export. - let path = if let Some(path) = first_non_private(cx, hir_id, &path) { + let path = if let Some(path) = first_non_private(cx, hir_id, path) { path } else { clean_path(path, cx) @@ -1796,7 +1793,7 @@ fn maybe_expand_private_type_alias<'tcx>( } Some(cx.enter_alias(args, def_id.to_def_id(), |cx| { - cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(&ty, cx)) + cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(ty, cx)) })) } @@ -1806,8 +1803,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T match ty.kind { TyKind::Never => Primitive(PrimitiveType::Never), TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))), - TyKind::Ref(ref l, ref m) => { - let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) }; + TyKind::Ref(l, ref m) => { + let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(l, cx)) }; BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), @@ -1843,17 +1840,17 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), TyKind::OpaqueDef(item_id, _, _) => { let item = cx.tcx.hir().item(item_id); - if let hir::ItemKind::OpaqueTy(ref ty) = item.kind { + if let hir::ItemKind::OpaqueTy(ty) = item.kind { ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) } else { unreachable!() } } TyKind::Path(_) => clean_qpath(ty, cx), - TyKind::TraitObject(bounds, ref lifetime, _) => { + TyKind::TraitObject(bounds, lifetime, _) => { let bounds = bounds.iter().map(|(bound, _)| clean_poly_trait_ref(bound, cx)).collect(); let lifetime = - if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None }; + if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None }; DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), @@ -2355,7 +2352,7 @@ pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx) } -pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext<'tcx>) -> Item { +pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) -> Item { clean_field_with_def_id( field.did, field.name, @@ -2378,7 +2375,7 @@ pub(crate) fn clean_field_with_def_id( Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx) } -pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item { +pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item { let discriminant = match variant.discr { ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), ty::VariantDiscr::Relative(_) => None, @@ -2526,7 +2523,7 @@ fn clean_generic_args<'tcx>( .filter_map(|arg| { Some(match arg { hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { - GenericArg::Lifetime(clean_lifetime(*lt, cx)) + GenericArg::Lifetime(clean_lifetime(lt, cx)) } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), @@ -2579,11 +2576,11 @@ fn clean_bare_fn_ty<'tcx>( BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params } } -pub(crate) fn reexport_chain<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn reexport_chain( + tcx: TyCtxt<'_>, import_def_id: LocalDefId, target_def_id: DefId, -) -> &'tcx [Reexport] { +) -> &[Reexport] { for child in tcx.module_children_local(tcx.local_parent(import_def_id)) { if child.res.opt_def_id() == Some(target_def_id) && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id()) @@ -2803,7 +2800,7 @@ fn clean_maybe_renamed_item<'tcx>( fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), - ItemKind::Macro(ref macro_def, MacroKind::Bang) => { + ItemKind::Macro(macro_def, MacroKind::Bang) => { let ty_vis = cx.tcx.visibility(def_id); MacroItem(Macro { // FIXME this shouldn't be false @@ -3134,9 +3131,7 @@ fn clean_assoc_item_constraint<'tcx>( } } -fn clean_bound_vars<'tcx>( - bound_vars: &'tcx ty::List<ty::BoundVariableKind>, -) -> Vec<GenericParamDef> { +fn clean_bound_vars(bound_vars: &ty::List<ty::BoundVariableKind>) -> Vec<GenericParamDef> { bound_vars .into_iter() .filter_map(|var| match var { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index c5e3aaab166..b8db82e540c 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -69,7 +69,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec<WP>) -> ThinVe pub(crate) fn merge_bounds( cx: &clean::DocContext<'_>, - bounds: &mut Vec<clean::GenericBound>, + bounds: &mut [clean::GenericBound], trait_did: DefId, assoc: clean::PathSegment, rhs: &clean::Term, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 63d71a73cdf..51da252da24 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -368,11 +368,11 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } impl Item { - pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> { + pub(crate) fn stability(&self, tcx: TyCtxt<'_>) -> Option<Stability> { self.def_id().and_then(|did| tcx.lookup_stability(did)) } - pub(crate) fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> { + pub(crate) fn const_stability(&self, tcx: TyCtxt<'_>) -> Option<ConstStability> { self.def_id().and_then(|did| tcx.lookup_const_stability(did)) } @@ -945,9 +945,9 @@ pub(crate) trait AttributesExt { where Self: 'a; - fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>; + fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_>; - fn iter<'a>(&'a self) -> Self::Attributes<'a>; + fn iter(&self) -> Self::Attributes<'_>; fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> { let sess = tcx.sess; @@ -1043,15 +1043,15 @@ impl AttributesExt for [ast::Attribute] { type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a; type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a; - fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> { + fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> { self.iter() .filter(move |attr| attr.has_name(name)) .filter_map(ast::Attribute::meta_item_list) .flatten() } - fn iter<'a>(&'a self) -> Self::Attributes<'a> { - self.into_iter() + fn iter(&self) -> Self::Attributes<'_> { + self.iter() } } @@ -1061,15 +1061,15 @@ impl AttributesExt for [(Cow<'_, ast::Attribute>, Option<DefId>)] { type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a where Self: 'a; - fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> { + fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> { AttributesExt::iter(self) .filter(move |attr| attr.has_name(name)) .filter_map(ast::Attribute::meta_item_list) .flatten() } - fn iter<'a>(&'a self) -> Self::Attributes<'a> { - self.into_iter().map(move |(attr, _)| match attr { + fn iter(&self) -> Self::Attributes<'_> { + self.iter().map(move |(attr, _)| match attr { Cow::Borrowed(attr) => *attr, Cow::Owned(attr) => attr, }) @@ -1389,7 +1389,7 @@ pub(crate) struct FnDecl { impl FnDecl { pub(crate) fn receiver_type(&self) -> Option<&Type> { - self.inputs.values.get(0).and_then(|v| v.to_receiver()) + self.inputs.values.first().and_then(|v| v.to_receiver()) } } @@ -1502,7 +1502,7 @@ impl Type { pub(crate) fn without_borrowed_ref(&self) -> &Type { let mut result = self; while let Type::BorrowedRef { type_, .. } = result { - result = &*type_; + result = type_; } result } @@ -1631,10 +1631,7 @@ impl Type { } pub(crate) fn is_self_type(&self) -> bool { - match *self { - SelfTy => true, - _ => false, - } + matches!(*self, Type::SelfTy) } pub(crate) fn generic_args(&self) -> Option<&GenericArgs> { @@ -1673,7 +1670,7 @@ impl Type { pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> { let t: PrimitiveType = match *self { Type::Path { ref path } => return Some(path.def_id()), - DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()), + DynTrait(ref bounds, _) => return bounds.first().map(|b| b.trait_.def_id()), Primitive(p) => return cache.primitive_locations.get(&p).cloned(), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.def_id(cache), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 68266f3506a..d826171aa61 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -321,9 +321,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { "({})", elts.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(", ") ), - PatKind::Box(p) => return name_from_pat(&*p), - PatKind::Deref(p) => format!("deref!({})", name_from_pat(&*p)), - PatKind::Ref(p, _) => return name_from_pat(&*p), + PatKind::Box(p) => return name_from_pat(p), + PatKind::Deref(p) => format!("deref!({})", name_from_pat(p)), + PatKind::Ref(p, _) => return name_from_pat(p), PatKind::Lit(..) => { warn!( "tried to get argument name from PatKind::Lit, which is silly in function arguments" @@ -333,7 +333,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { PatKind::Range(..) => return kw::Underscore, PatKind::Slice(begin, ref mid, end) => { let begin = begin.iter().map(|p| name_from_pat(p).to_string()); - let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); + let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(p))).into_iter(); let end = end.iter().map(|p| name_from_pat(p).to_string()); format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", ")) } @@ -344,7 +344,7 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { let s = if let Some(def) = def.as_local() { - rendered_const(cx.tcx, &cx.tcx.hir().body_owned_by(def), def) + rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def), def) } else { inline::print_inlined_const(cx.tcx, def) }; @@ -383,7 +383,7 @@ pub(crate) fn print_evaluated_const( fn format_integer_with_underscore_sep(num: &str) -> String { let num_chars: Vec<_> = num.chars().collect(); - let mut num_start_index = if num_chars.get(0) == Some(&'-') { 1 } else { 0 }; + let mut num_start_index = if num_chars.first() == Some(&'-') { 1 } else { 0 }; let chunk_size = match num[num_start_index..].as_bytes() { [b'0', b'b' | b'x', ..] => { num_start_index += 2; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9e9d8f02a2e..9e7b69ec45f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -360,7 +360,7 @@ impl Options { return None; } - if rustc_driver::describe_flag_categories(early_dcx, &matches) { + if rustc_driver::describe_flag_categories(early_dcx, matches) { return None; } @@ -374,7 +374,7 @@ impl Options { let codegen_options = CodegenOptions::build(early_dcx, matches); let unstable_opts = UnstableOptions::build(early_dcx, matches); - let remap_path_prefix = match parse_remap_path_prefix(&matches) { + let remap_path_prefix = match parse_remap_path_prefix(matches) { Ok(prefix_mappings) => prefix_mappings, Err(err) => { early_dcx.early_fatal(err); @@ -486,7 +486,7 @@ impl Options { _ => dcx.fatal("too many file operands"), } }; - let input = make_input(early_dcx, &input); + let input = make_input(early_dcx, input); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 08a4a3f3fb2..760514f40fd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -288,7 +288,7 @@ pub(crate) fn create_config( let hir = tcx.hir(); let body = hir.body_owned_by(def_id); debug!("visiting body for {def_id:?}"); - EmitIgnoredResolutionErrors::new(tcx).visit_body(&body); + EmitIgnoredResolutionErrors::new(tcx).visit_body(body); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 743c1ed507e..1ae66fddda6 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -272,7 +272,7 @@ pub(crate) fn run_tests( let mut tests_runner = runner::DocTestRunner::new(); let rustdoc_test_options = IndividualTestOptions::new( - &rustdoc_options, + rustdoc_options, &Some(format!("merged_doctest_{edition}")), PathBuf::from(format!("doctest_{edition}.rs")), ); @@ -307,7 +307,7 @@ pub(crate) fn run_tests( doctest, scraped_test, opts.clone(), - Arc::clone(&rustdoc_options), + Arc::clone(rustdoc_options), unused_extern_reports.clone(), )); } @@ -316,7 +316,7 @@ pub(crate) fn run_tests( // We need to call `test_main` even if there is no doctest to run to get the output // `running 0 tests...`. if ran_edition_tests == 0 || !standalone_tests.is_empty() { - standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice())); + standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(b.desc.name.as_slice())); test::test_main(&test_args, standalone_tests, None); } if nb_errors != 0 { @@ -421,7 +421,7 @@ fn add_exe_suffix(input: String, target: &TargetTriple) -> String { } fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { - let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary].into_iter()); + let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary]); let exe = args.next().expect("unable to create rustc command"); let mut command = Command::new(exe); @@ -452,7 +452,7 @@ pub(crate) struct RunnableDocTest { impl RunnableDocTest { fn path_for_merged_doctest(&self) -> PathBuf { - self.test_opts.outdir.path().join(&format!("doctest_{}.rs", self.edition)) + self.test_opts.outdir.path().join(format!("doctest_{}.rs", self.edition)) } } @@ -477,13 +477,13 @@ fn run_test( .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc")); let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); - compiler.arg(&format!("@{}", doctest.global_opts.args_file.display())); + compiler.arg(format!("@{}", doctest.global_opts.args_file.display())); if let Some(sysroot) = &rustdoc_options.maybe_sysroot { compiler.arg(format!("--sysroot={}", sysroot.display())); } - compiler.arg("--edition").arg(&doctest.edition.to_string()); + compiler.arg("--edition").arg(doctest.edition.to_string()); if !doctest.is_multiple_tests { // Setting these environment variables is unneeded if this is a merged doctest. compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path); @@ -692,7 +692,7 @@ impl IndividualTestOptions { fn new(options: &RustdocOptions, test_id: &Option<String>, test_path: PathBuf) -> Self { let outdir = if let Some(ref path) = options.persist_doctests { let mut path = path.clone(); - path.push(&test_id.as_deref().unwrap_or_else(|| "<doctest>")); + path.push(&test_id.as_deref().unwrap_or("<doctest>")); if let Err(err) = std::fs::create_dir_all(&path) { eprintln!("Couldn't create directory for doctest executables: {err}"); diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index aed079e5887..9de312a413a 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -311,7 +311,7 @@ fn parse_source( } ast::ItemKind::ExternCrate(original) => { if !info.found_extern_crate - && let Some(ref crate_name) = crate_name + && let Some(crate_name) = crate_name { info.found_extern_crate = match original { Some(name) => name.as_str() == *crate_name, diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index 4806d865589..9a237f8684d 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -73,7 +73,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { use rustc_session::config::Input; let input_str = match &options.input { Input::File(path) => { - read_to_string(&path).map_err(|err| format!("{}: {err}", path.display()))? + read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))? } Input::Str { name: _, input } => input.clone(), }; diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index d49fa3ac5ac..9cb220ef7ba 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -98,8 +98,10 @@ impl DocTestRunner { code.push_str("extern crate test;\n"); - let test_args = - test_args.iter().map(|arg| format!("{arg:?}.to_string(),")).collect::<String>(); + let test_args = test_args.iter().fold(String::new(), |mut x, arg| { + write!(x, "{arg:?}.to_string(),").unwrap(); + x + }); write!( code, "\ diff --git a/src/librustdoc/error.rs b/src/librustdoc/error.rs index 6ed7eab1aba..7876125f7fd 100644 --- a/src/librustdoc/error.rs +++ b/src/librustdoc/error.rs @@ -39,7 +39,7 @@ macro_rules! try_none { match $e { Some(e) => e, None => { - return Err(<crate::error::Error as crate::docfs::PathError>::new( + return Err(<$crate::error::Error as $crate::docfs::PathError>::new( io::Error::new(io::ErrorKind::Other, "not found"), $file, )); diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 947bae99305..90942d87f72 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { None }; if let Some(name) = search_name { - add_item_to_search_index(self.tcx, &mut self.cache, &item, name) + add_item_to_search_index(self.tcx, self.cache, &item, name) } // Keep track of the fully qualified path for this item. @@ -452,7 +452,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // or if item is tuple struct/variant field (name is a number -> not useful for search). if cache.stripped_mod || item.type_() == ItemType::StructField - && name.as_str().chars().all(|c| c.is_digit(10)) + && name.as_str().chars().all(|c| c.is_ascii_digit()) { return; } @@ -463,7 +463,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It } clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { let last = cache.parent_stack.last().expect("parent_stack is empty 2"); - let parent_did = match &*last { + let parent_did = match last { // impl Trait for &T { fn method(self); } // // When generating a function index with the above shape, we want it @@ -471,9 +471,9 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // show up as `T::method`, rather than `reference::method`, in the search // results page. ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => { - type_.def_id(&cache) + type_.def_id(cache) } - ParentStackItem::Impl { for_, .. } => for_.def_id(&cache), + ParentStackItem::Impl { for_, .. } => for_.def_id(cache), ParentStackItem::Type(item_id) => item_id.as_def_id(), }; let Some(parent_did) = parent_did else { return }; @@ -538,7 +538,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It None }; let search_type = get_function_type_for_search( - &item, + item, tcx, clean_impl_generics(cache.parent_stack.last()).as_ref(), parent_did, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5cbf8c5e19f..530241f9a13 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -633,7 +633,7 @@ fn generate_item_def_id_path( let module_fqp = to_module_fqp(shortty, &fqp); let mut is_remote = false; - let url_parts = url_parts(cx.cache(), def_id, &module_fqp, &cx.current, &mut is_remote)?; + let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?; let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?; if def_id == original_def_id { return Ok((url_parts, shortty, fqp)); @@ -811,7 +811,7 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont // primitives are documented in a crate, but not actually part of it &fqp[fqp.len() - 1..] } else { - &fqp + fqp }; if let &Some(UrlFragment::Item(id)) = fragment { write!(buf, "{} ", cx.tcx().def_descr(id)); @@ -820,7 +820,7 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont } write!(buf, "{}", cx.tcx().item_name(id)); } else if !fqp.is_empty() { - let mut fqp_it = fqp.into_iter(); + let mut fqp_it = fqp.iter(); write!(buf, "{shortty} {}", fqp_it.next().unwrap()); for component in fqp_it { write!(buf, "::{component}"); @@ -830,13 +830,13 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont } /// Used to render a [`clean::Path`]. -fn resolved_path<'cx>( +fn resolved_path( w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, print_all: bool, use_absolute: bool, - cx: &'cx Context<'_>, + cx: &Context<'_>, ) -> fmt::Result { let last = path.segments.last().unwrap(); @@ -996,11 +996,11 @@ pub(crate) fn anchor<'a, 'cx: 'a>( }) } -fn fmt_type<'cx>( +fn fmt_type( t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool, - cx: &'cx Context<'_>, + cx: &Context<'_>, ) -> fmt::Result { trace!("fmt_type(t = {t:?})"); @@ -1493,9 +1493,8 @@ impl clean::FnDecl { } clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => { write!(f, "{amp}")?; - match lifetime { - Some(lt) => write!(f, "{lt} ", lt = lt.print())?, - None => {} + if let Some(lt) = lifetime { + write!(f, "{lt} ", lt = lt.print())?; } write!(f, "{mutability}self", mutability = mutability.print_with_space())?; } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index a18b7a252a4..60dc142b9ff 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -75,11 +75,11 @@ pub(crate) fn write_shared( let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand" - let external_crates = hack_get_external_crate_names(&cx.dst)?; + let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?; let info = CrateInfo { src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, - all_crates: AllCratesPart::get(crate_name_json.clone())?, + all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, @@ -291,10 +291,13 @@ impl AllCratesPart { SortedTemplate::from_before_after("window.ALL_CRATES = [", "];") } - fn get(crate_name_json: OrderedJson) -> Result<PartsAndLocations<Self>, Error> { + fn get( + crate_name_json: OrderedJson, + resource_suffix: &str, + ) -> Result<PartsAndLocations<Self>, Error> { // external hack_get_external_crate_names not needed here, because // there's no way that we write the search index but not crates.js - let path = PathBuf::from("crates.js"); + let path = suffix_path("crates.js", resource_suffix); Ok(PartsAndLocations::with(path, crate_name_json)) } } @@ -305,8 +308,11 @@ impl AllCratesPart { /// /// This is to match the current behavior of rustdoc, which allows you to get all crates /// on the index page, even if --enable-index-page is only passed to the last crate. -fn hack_get_external_crate_names(doc_root: &Path) -> Result<Vec<String>, Error> { - let path = doc_root.join("crates.js"); +fn hack_get_external_crate_names( + doc_root: &Path, + resource_suffix: &str, +) -> Result<Vec<String>, Error> { + let path = doc_root.join(suffix_path("crates.js", resource_suffix)); let Ok(content) = fs::read_to_string(&path) else { // they didn't emit invocation specific, so we just say there were no crates return Ok(Vec::default()); diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs index 4d1874b7df5..e282cd99e43 100644 --- a/src/librustdoc/html/render/write_shared/tests.rs +++ b/src/librustdoc/html/render/write_shared/tests.rs @@ -6,10 +6,10 @@ use crate::html::render::write_shared::*; fn hack_external_crate_names() { let path = tempfile::TempDir::new().unwrap(); let path = path.path(); - let crates = hack_get_external_crate_names(&path).unwrap(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); assert!(crates.is_empty()); fs::write(path.join("crates.js"), r#"window.ALL_CRATES = ["a","b","c"];"#).unwrap(); - let crates = hack_get_external_crate_names(&path).unwrap(); + let crates = hack_get_external_crate_names(&path, "").unwrap(); assert_eq!(crates, ["a".to_string(), "b".to_string(), "c".to_string()]); } @@ -60,7 +60,7 @@ fn all_crates_template() { #[test] fn all_crates_parts() { - let parts = AllCratesPart::get(OrderedJson::serialize("crate").unwrap()).unwrap(); + let parts = AllCratesPart::get(OrderedJson::serialize("crate").unwrap(), "").unwrap(); assert_eq!(&parts.parts[0].0, Path::new("crates.js")); assert_eq!(&parts.parts[0].1.to_string(), r#""crate""#); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index be0ec425946..6f575e60ed4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -16,6 +16,7 @@ if (!Array.prototype.toSpliced) { } (function() { +// ==================== Core search logic begin ==================== // This mapping table should match the discriminants of // `rustdoc::formats::item_type::ItemType` type in Rust. const itemTypes = [ @@ -48,35 +49,6 @@ const itemTypes = [ "generic", ]; -const longItemTypes = [ - "keyword", - "primitive type", - "module", - "extern crate", - "re-export", - "struct", - "enum", - "function", - "type alias", - "static", - "trait", - "", - "trait method", - "method", - "struct field", - "enum variant", - "macro", - "assoc type", - "constant", - "assoc const", - "union", - "foreign type", - "existential type", - "attribute macro", - "derive macro", - "trait alias", -]; - // used for special search precedence const TY_GENERIC = itemTypes.indexOf("generic"); const TY_IMPORT = itemTypes.indexOf("import"); @@ -93,44 +65,8 @@ const UNBOXING_LIMIT = 5; const REGEX_IDENT = /\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy; const REGEX_INVALID_TYPE_FILTER = /[^a-z]/ui; -// In the search display, allows to switch between tabs. -function printTab(nb) { - let iter = 0; - let foundCurrentTab = false; - let foundCurrentResultSet = false; - onEachLazy(document.getElementById("search-tabs").childNodes, elem => { - if (nb === iter) { - addClass(elem, "selected"); - foundCurrentTab = true; - } else { - removeClass(elem, "selected"); - } - iter += 1; - }); - const isTypeSearch = (nb > 0 || iter === 1); - iter = 0; - onEachLazy(document.getElementById("results").childNodes, elem => { - if (nb === iter) { - addClass(elem, "active"); - foundCurrentResultSet = true; - } else { - removeClass(elem, "active"); - } - iter += 1; - }); - if (foundCurrentTab && foundCurrentResultSet) { - searchState.currentTab = nb; - // Corrections only kick in on type-based searches. - const correctionsElem = document.getElementsByClassName("search-corrections"); - if (isTypeSearch) { - removeClass(correctionsElem[0], "hidden"); - } else { - addClass(correctionsElem[0], "hidden"); - } - } else if (nb !== 0) { - printTab(0); - } -} +const MAX_RESULTS = 200; +const NO_TYPE_FILTER = -1; /** * The [edit distance] is a metric for measuring the difference between two strings. @@ -240,1001 +176,1564 @@ function editDistance(a, b, limit) { return editDistanceState.calculate(a, b, limit); } -function initSearch(rawSearchIndex) { - const MAX_RESULTS = 200; - const NO_TYPE_FILTER = -1; - /** - * @type {Array<Row>} - */ - let searchIndex; - /** - * @type {Map<String, RoaringBitmap>} - */ - let searchIndexDeprecated; - /** - * @type {Map<String, RoaringBitmap>} - */ - let searchIndexEmptyDesc; - /** - * @type {Uint32Array} - */ - let functionTypeFingerprint; - let currentResults; - /** - * Map from normalized type names to integers. Used to make type search - * more efficient. - * - * @type {Map<string, {id: integer, assocOnly: boolean}>} - */ - const typeNameIdMap = new Map(); - const ALIASES = new Map(); - - /** - * Special type name IDs for searching by array. - */ - const typeNameIdOfArray = buildTypeMapIndex("array"); - /** - * Special type name IDs for searching by slice. - */ - const typeNameIdOfSlice = buildTypeMapIndex("slice"); - /** - * Special type name IDs for searching by both array and slice (`[]` syntax). - */ - const typeNameIdOfArrayOrSlice = buildTypeMapIndex("[]"); - /** - * Special type name IDs for searching by tuple. - */ - const typeNameIdOfTuple = buildTypeMapIndex("tuple"); - /** - * Special type name IDs for searching by unit. - */ - const typeNameIdOfUnit = buildTypeMapIndex("unit"); - /** - * Special type name IDs for searching by both tuple and unit (`()` syntax). - */ - const typeNameIdOfTupleOrUnit = buildTypeMapIndex("()"); - /** - * Special type name IDs for searching `fn`. - */ - const typeNameIdOfFn = buildTypeMapIndex("fn"); - /** - * Special type name IDs for searching `fnmut`. - */ - const typeNameIdOfFnMut = buildTypeMapIndex("fnmut"); - /** - * Special type name IDs for searching `fnonce`. - */ - const typeNameIdOfFnOnce = buildTypeMapIndex("fnonce"); - /** - * Special type name IDs for searching higher order functions (`->` syntax). - */ - const typeNameIdOfHof = buildTypeMapIndex("->"); - - /** - * Add an item to the type Name->ID map, or, if one already exists, use it. - * Returns the number. If name is "" or null, return null (pure generic). - * - * This is effectively string interning, so that function matching can be - * done more quickly. Two types with the same name but different item kinds - * get the same ID. - * - * @param {string} name - * @param {boolean} isAssocType - True if this is an assoc type - * - * @returns {integer} - */ - function buildTypeMapIndex(name, isAssocType) { - if (name === "" || name === null) { - return null; - } - - if (typeNameIdMap.has(name)) { - const obj = typeNameIdMap.get(name); - obj.assocOnly = isAssocType && obj.assocOnly; - return obj.id; - } else { - const id = typeNameIdMap.size; - typeNameIdMap.set(name, {id, assocOnly: isAssocType}); - return id; - } - } - - function isSpecialStartCharacter(c) { - return "<\"".indexOf(c) !== -1; - } +function isEndCharacter(c) { + return "=,>-])".indexOf(c) !== -1; +} - function isEndCharacter(c) { - return "=,>-])".indexOf(c) !== -1; - } +/** + * Returns `true` if the given `c` character is a separator. + * + * @param {string} c + * + * @return {boolean} + */ +function isSeparatorCharacter(c) { + return c === "," || c === "="; +} - function itemTypeFromName(typename) { - const index = itemTypes.findIndex(i => i === typename); - if (index < 0) { - throw ["Unknown type filter ", typename]; - } - return index; - } +/** + * Returns `true` if the current parser position is starting with "->". + * + * @param {ParserState} parserState + * + * @return {boolean} + */ +function isReturnArrow(parserState) { + return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "->"; +} - /** - * If we encounter a `"`, then we try to extract the string from it until we find another `"`. - * - * This function will throw an error in the following cases: - * * There is already another string element. - * * We are parsing a generic argument. - * * There is more than one element. - * * There is no closing `"`. - * - * @param {ParsedQuery} query - * @param {ParserState} parserState - * @param {boolean} isInGenerics - */ - function getStringElem(query, parserState, isInGenerics) { - if (isInGenerics) { - throw ["Unexpected ", "\"", " in generics"]; - } else if (query.literalSearch) { - throw ["Cannot have more than one literal search element"]; - } else if (parserState.totalElems - parserState.genericsElems > 0) { - throw ["Cannot use literal search when there is more than one element"]; +/** + * Increase current parser position until it doesn't find a whitespace anymore. + * + * @param {ParserState} parserState + */ +function skipWhitespace(parserState) { + while (parserState.pos < parserState.userQuery.length) { + const c = parserState.userQuery[parserState.pos]; + if (c !== " ") { + break; } parserState.pos += 1; - const start = parserState.pos; - const end = getIdentEndPosition(parserState); - if (parserState.pos >= parserState.length) { - throw ["Unclosed ", "\""]; - } else if (parserState.userQuery[end] !== "\"") { - throw ["Unexpected ", parserState.userQuery[end], " in a string element"]; - } else if (start === end) { - throw ["Cannot have empty string element"]; - } - // To skip the quote at the end. - parserState.pos += 1; - query.literalSearch = true; - } - - /** - * Returns `true` if the current parser position is starting with "::". - * - * @param {ParserState} parserState - * - * @return {boolean} - */ - function isPathStart(parserState) { - return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "::"; - } - - /** - * Returns `true` if the current parser position is starting with "->". - * - * @param {ParserState} parserState - * - * @return {boolean} - */ - function isReturnArrow(parserState) { - return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "->"; } +} - /** - * If the current parser position is at the beginning of an identifier, - * move the position to the end of it and return `true`. Otherwise, return `false`. - * - * @param {ParserState} parserState - * - * @return {boolean} - */ - function consumeIdent(parserState) { - REGEX_IDENT.lastIndex = parserState.pos; - const match = parserState.userQuery.match(REGEX_IDENT); - if (match) { - parserState.pos += match[0].length; +/** + * Returns `true` if the previous character is `lookingFor`. + * + * @param {ParserState} parserState + * @param {String} lookingFor + * + * @return {boolean} + */ +function prevIs(parserState, lookingFor) { + let pos = parserState.pos; + while (pos > 0) { + const c = parserState.userQuery[pos - 1]; + if (c === lookingFor) { return true; + } else if (c !== " ") { + break; } - return false; + pos -= 1; } + return false; +} - /** - * Returns `true` if the given `c` character is a separator. - * - * @param {string} c - * - * @return {boolean} - */ - function isSeparatorCharacter(c) { - return c === "," || c === "="; - } +/** + * Returns `true` if the last element in the `elems` argument has generics. + * + * @param {Array<QueryElement>} elems + * @param {ParserState} parserState + * + * @return {boolean} + */ +function isLastElemGeneric(elems, parserState) { + return (elems.length > 0 && elems[elems.length - 1].generics.length > 0) || + prevIs(parserState, ">"); +} - /** - * Returns `true` if the given `c` character is a path separator. For example - * `:` in `a::b` or a whitespace in `a b`. - * - * @param {string} c - * - * @return {boolean} - */ - function isPathSeparator(c) { - return c === ":" || c === " "; +function getFilteredNextElem(query, parserState, elems, isInGenerics) { + const start = parserState.pos; + if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { + throw ["Expected type filter before ", ":"]; } - - /** - * Returns `true` if the previous character is `lookingFor`. - * - * @param {ParserState} parserState - * @param {String} lookingFor - * - * @return {boolean} - */ - function prevIs(parserState, lookingFor) { - let pos = parserState.pos; - while (pos > 0) { - const c = parserState.userQuery[pos - 1]; - if (c === lookingFor) { - return true; - } else if (c !== " ") { - break; - } - pos -= 1; + getNextElem(query, parserState, elems, isInGenerics); + if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { + if (parserState.typeFilter !== null) { + throw [ + "Unexpected ", + ":", + " (expected path after type filter ", + parserState.typeFilter + ":", + ")", + ]; } - return false; + if (elems.length === 0) { + throw ["Expected type filter before ", ":"]; + } else if (query.literalSearch) { + throw ["Cannot use quotes on type filter"]; + } + // The type filter doesn't count as an element since it's a modifier. + const typeFilterElem = elems.pop(); + checkExtraTypeFilterCharacters(start, parserState); + parserState.typeFilter = typeFilterElem.name; + parserState.pos += 1; + parserState.totalElems -= 1; + query.literalSearch = false; + getNextElem(query, parserState, elems, isInGenerics); } +} - /** - * Returns `true` if the last element in the `elems` argument has generics. - * - * @param {Array<QueryElement>} elems - * @param {ParserState} parserState - * - * @return {boolean} - */ - function isLastElemGeneric(elems, parserState) { - return (elems.length > 0 && elems[elems.length - 1].generics.length > 0) || - prevIs(parserState, ">"); +/** + * This function parses the next query element until it finds `endChar`, + * calling `getNextElem` to collect each element. + * + * If there is no `endChar`, this function will implicitly stop at the end + * without raising an error. + * + * @param {ParsedQuery} query + * @param {ParserState} parserState + * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added. + * @param {string} endChar - This function will stop when it'll encounter this + * character. + * @returns {{foundSeparator: bool}} + */ +function getItemsBefore(query, parserState, elems, endChar) { + let foundStopChar = true; + let foundSeparator = false; + + // If this is a generic, keep the outer item's type filter around. + const oldTypeFilter = parserState.typeFilter; + parserState.typeFilter = null; + const oldIsInBinding = parserState.isInBinding; + parserState.isInBinding = null; + + // ML-style Higher Order Function notation + // + // a way to search for any closure or fn pointer regardless of + // which closure trait is used + // + // Looks like this: + // + // `option<t>, (t -> u) -> option<u>` + // ^^^^^^ + // + // The Rust-style closure notation is implemented in getNextElem + let hofParameters = null; + + let extra = ""; + if (endChar === ">") { + extra = "<"; + } else if (endChar === "]") { + extra = "["; + } else if (endChar === ")") { + extra = "("; + } else if (endChar === "") { + extra = "->"; + } else { + extra = endChar; } - /** - * Increase current parser position until it doesn't find a whitespace anymore. - * - * @param {ParserState} parserState - */ - function skipWhitespace(parserState) { - while (parserState.pos < parserState.userQuery.length) { - const c = parserState.userQuery[parserState.pos]; - if (c !== " ") { - break; + while (parserState.pos < parserState.length) { + const c = parserState.userQuery[parserState.pos]; + if (c === endChar) { + if (parserState.isInBinding) { + throw ["Unexpected ", endChar, " after ", "="]; + } + break; + } else if (endChar !== "" && isReturnArrow(parserState)) { + // ML-style HOF notation only works when delimited in something, + // otherwise a function arrow starts the return type of the top + if (parserState.isInBinding) { + throw ["Unexpected ", "->", " after ", "="]; } + hofParameters = [...elems]; + elems.length = 0; + parserState.pos += 2; + foundStopChar = true; + foundSeparator = false; + continue; + } else if (c === " ") { + parserState.pos += 1; + continue; + } else if (isSeparatorCharacter(c)) { parserState.pos += 1; + foundStopChar = true; + foundSeparator = true; + continue; + } else if (c === ":" && isPathStart(parserState)) { + throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; + } else if (isEndCharacter(c)) { + throw ["Unexpected ", c, " after ", extra]; + } + if (!foundStopChar) { + let extra = []; + if (isLastElemGeneric(query.elems, parserState)) { + extra = [" after ", ">"]; + } else if (prevIs(parserState, "\"")) { + throw ["Cannot have more than one element if you use quotes"]; + } + if (endChar !== "") { + throw [ + "Expected ", + ",", + ", ", + "=", + ", or ", + endChar, + ...extra, + ", found ", + c, + ]; + } + throw [ + "Expected ", + ",", + " or ", + "=", + ...extra, + ", found ", + c, + ]; } + const posBefore = parserState.pos; + getFilteredNextElem(query, parserState, elems, endChar !== ""); + if (endChar !== "" && parserState.pos >= parserState.length) { + throw ["Unclosed ", extra]; + } + // This case can be encountered if `getNextElem` encountered a "stop character" + // right from the start. For example if you have `,,` or `<>`. In this case, + // we simply move up the current position to continue the parsing. + if (posBefore === parserState.pos) { + parserState.pos += 1; + } + foundStopChar = false; } - - function makePrimitiveElement(name, extra) { - return Object.assign({ - name, - id: null, - fullPath: [name], - pathWithoutLast: [], - pathLast: name, - normalizedPathLast: name, - generics: [], - bindings: new Map(), - typeFilter: "primitive", - bindingName: null, - }, extra); + if (parserState.pos >= parserState.length && endChar !== "") { + throw ["Unclosed ", extra]; + } + // We are either at the end of the string or on the `endChar` character, let's move + // forward in any case. + parserState.pos += 1; + + if (hofParameters) { + // Commas in a HOF don't cause wrapping parens to become a tuple. + // If you want a one-tuple with a HOF in it, write `((a -> b),)`. + foundSeparator = false; + // HOFs can't have directly nested bindings. + if ([...elems, ...hofParameters].some(x => x.bindingName) + || parserState.isInBinding) { + throw ["Unexpected ", "=", " within ", "->"]; + } + // HOFs are represented the same way closures are. + // The arguments are wrapped in a tuple, and the output + // is a binding, even though the compiler doesn't technically + // represent fn pointers that way. + const hofElem = makePrimitiveElement("->", { + generics: hofParameters, + bindings: new Map([["output", [...elems]]]), + typeFilter: null, + }); + elems.length = 0; + elems[0] = hofElem; } - /** - * @param {ParsedQuery} query - * @param {ParserState} parserState - * @param {string} name - Name of the query element. - * @param {Array<QueryElement>} generics - List of generics of this query element. - * - * @return {QueryElement} - The newly created `QueryElement`. - */ - function createQueryElement(query, parserState, name, generics, isInGenerics) { - const path = name.trim(); - if (path.length === 0 && generics.length === 0) { - throw ["Unexpected ", parserState.userQuery[parserState.pos]]; - } - if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { - throw ["Cannot have more than one element if you use quotes"]; + parserState.typeFilter = oldTypeFilter; + parserState.isInBinding = oldIsInBinding; + + return { foundSeparator }; +} + +/** + * @param {ParsedQuery} query + * @param {ParserState} parserState + * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added. + * @param {boolean} isInGenerics + */ +function getNextElem(query, parserState, elems, isInGenerics) { + const generics = []; + + skipWhitespace(parserState); + let start = parserState.pos; + let end; + if ("[(".indexOf(parserState.userQuery[parserState.pos]) !== -1) { + let endChar = ")"; + let name = "()"; + let friendlyName = "tuple"; + + if (parserState.userQuery[parserState.pos] === "[") { + endChar = "]"; + name = "[]"; + friendlyName = "slice"; } + parserState.pos += 1; + const { foundSeparator } = getItemsBefore(query, parserState, generics, endChar); const typeFilter = parserState.typeFilter; + const bindingName = parserState.isInBinding; parserState.typeFilter = null; - if (name === "!") { + parserState.isInBinding = null; + for (const gen of generics) { + if (gen.bindingName !== null) { + throw ["Type parameter ", "=", ` cannot be within ${friendlyName} `, name]; + } + } + if (name === "()" && !foundSeparator && generics.length === 1 + && typeFilter === null) { + elems.push(generics[0]); + } else if (name === "()" && generics.length === 1 && generics[0].name === "->") { + // `primitive:(a -> b)` parser to `primitive:"->"<output=b, (a,)>` + // not `primitive:"()"<"->"<output=b, (a,)>>` + generics[0].typeFilter = typeFilter; + elems.push(generics[0]); + } else { if (typeFilter !== null && typeFilter !== "primitive") { throw [ - "Invalid search type: primitive never type ", - "!", + "Invalid search type: primitive ", + name, " and ", typeFilter, " both specified", ]; } - if (generics.length !== 0) { - throw [ - "Never type ", - "!", - " does not accept generic parameters", - ]; - } - const bindingName = parserState.isInBinding; - parserState.isInBinding = null; - return makePrimitiveElement("never", { bindingName }); - } - const quadcolon = /::\s*::/.exec(path); - if (path.startsWith("::")) { - throw ["Paths cannot start with ", "::"]; - } else if (path.endsWith("::")) { - throw ["Paths cannot end with ", "::"]; - } else if (quadcolon !== null) { - throw ["Unexpected ", quadcolon[0]]; - } - const pathSegments = path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/); - // In case we only have something like `<p>`, there is no name. - if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) { - if (generics.length > 0 || prevIs(parserState, ">")) { - throw ["Found generics without a path"]; - } else { - throw ["Unexpected ", parserState.userQuery[parserState.pos]]; + parserState.totalElems += 1; + if (isInGenerics) { + parserState.genericsElems += 1; } + elems.push(makePrimitiveElement(name, { bindingName, generics })); } - for (const [i, pathSegment] of pathSegments.entries()) { - if (pathSegment === "!") { - if (i !== 0) { - throw ["Never type ", "!", " is not associated item"]; - } - pathSegments[i] = "never"; - } - } - parserState.totalElems += 1; - if (isInGenerics) { - parserState.genericsElems += 1; + } else if (parserState.userQuery[parserState.pos] === "&") { + if (parserState.typeFilter !== null && parserState.typeFilter !== "primitive") { + throw [ + "Invalid search type: primitive ", + "&", + " and ", + parserState.typeFilter, + " both specified", + ]; } - const bindingName = parserState.isInBinding; - parserState.isInBinding = null; - const bindings = new Map(); - const pathLast = pathSegments[pathSegments.length - 1]; - return { - name: name.trim(), - id: null, - fullPath: pathSegments, - pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1), - pathLast, - normalizedPathLast: pathLast.replace(/_/g, ""), - generics: generics.filter(gen => { - // Syntactically, bindings are parsed as generics, - // but the query engine treats them differently. - if (gen.bindingName !== null) { - if (gen.name !== null) { - gen.bindingName.generics.unshift(gen); - } - bindings.set(gen.bindingName.name, gen.bindingName.generics); - return false; - } - return true; - }), - bindings, - typeFilter, - bindingName, - }; - } - - /** - * This function goes through all characters until it reaches an invalid ident character or the - * end of the query. It returns the position of the last character of the ident. - * - * @param {ParserState} parserState - * - * @return {integer} - */ - function getIdentEndPosition(parserState) { - let afterIdent = consumeIdent(parserState); - let end = parserState.pos; - let macroExclamation = -1; - while (parserState.pos < parserState.length) { - const c = parserState.userQuery[parserState.pos]; - if (c === "!") { - if (macroExclamation !== -1) { - throw ["Cannot have more than one ", "!", " in an ident"]; - } else if (parserState.pos + 1 < parserState.length) { - const pos = parserState.pos; - parserState.pos++; - const beforeIdent = consumeIdent(parserState); - parserState.pos = pos; - if (beforeIdent) { - throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; - } - } - if (afterIdent) macroExclamation = parserState.pos; - } else if (isPathSeparator(c)) { - if (c === ":") { - if (!isPathStart(parserState)) { - break; - } - // Skip current ":". - parserState.pos += 1; - } else { - while (parserState.pos + 1 < parserState.length) { - const next_c = parserState.userQuery[parserState.pos + 1]; - if (next_c !== " ") { - break; - } - parserState.pos += 1; - } - } - if (macroExclamation !== -1) { - throw ["Cannot have associated items in macros"]; - } - } else if ( - c === "[" || - c === "(" || - isEndCharacter(c) || - isSpecialStartCharacter(c) || - isSeparatorCharacter(c) - ) { - break; - } else if (parserState.pos > 0) { - throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1], - " (not a valid identifier)"]; - } else { - throw ["Unexpected ", c, " (not a valid identifier)"]; - } + parserState.typeFilter = null; + parserState.pos += 1; + let c = parserState.userQuery[parserState.pos]; + while (c === " " && parserState.pos < parserState.length) { parserState.pos += 1; - afterIdent = consumeIdent(parserState); - end = parserState.pos; + c = parserState.userQuery[parserState.pos]; } - if (macroExclamation !== -1) { - if (parserState.typeFilter === null) { - parserState.typeFilter = "macro"; - } else if (parserState.typeFilter !== "macro") { - throw [ - "Invalid search type: macro ", - "!", - " and ", - parserState.typeFilter, - " both specified", - ]; - } - end = macroExclamation; + const generics = []; + if (parserState.userQuery.slice(parserState.pos, parserState.pos + 3) === "mut") { + generics.push(makePrimitiveElement("mut", { typeFilter: "keyword" })); + parserState.pos += 3; + c = parserState.userQuery[parserState.pos]; } - return end; - } - - function getFilteredNextElem(query, parserState, elems, isInGenerics) { - const start = parserState.pos; - if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { - throw ["Expected type filter before ", ":"]; + while (c === " " && parserState.pos < parserState.length) { + parserState.pos += 1; + c = parserState.userQuery[parserState.pos]; + } + if (!isEndCharacter(c) && parserState.pos < parserState.length) { + getFilteredNextElem(query, parserState, generics, isInGenerics); + } + elems.push(makePrimitiveElement("reference", { generics })); + } else { + const isStringElem = parserState.userQuery[start] === "\""; + // We handle the strings on their own mostly to make code easier to follow. + if (isStringElem) { + start += 1; + getStringElem(query, parserState, isInGenerics); + end = parserState.pos - 1; + } else { + end = getIdentEndPosition(parserState); } - getNextElem(query, parserState, elems, isInGenerics); - if (parserState.userQuery[parserState.pos] === ":" && !isPathStart(parserState)) { - if (parserState.typeFilter !== null) { - throw [ - "Unexpected ", - ":", - " (expected path after type filter ", - parserState.typeFilter + ":", - ")", - ]; - } - if (elems.length === 0) { - throw ["Expected type filter before ", ":"]; - } else if (query.literalSearch) { - throw ["Cannot use quotes on type filter"]; + if (parserState.pos < parserState.length && + parserState.userQuery[parserState.pos] === "<" + ) { + if (start >= end) { + throw ["Found generics without a path"]; } - // The type filter doesn't count as an element since it's a modifier. - const typeFilterElem = elems.pop(); - checkExtraTypeFilterCharacters(start, parserState); - parserState.typeFilter = typeFilterElem.name; parserState.pos += 1; - parserState.totalElems -= 1; - query.literalSearch = false; - getNextElem(query, parserState, elems, isInGenerics); - } - } - - /** - * @param {ParsedQuery} query - * @param {ParserState} parserState - * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added. - * @param {boolean} isInGenerics - */ - function getNextElem(query, parserState, elems, isInGenerics) { - const generics = []; - - skipWhitespace(parserState); - let start = parserState.pos; - let end; - if ("[(".indexOf(parserState.userQuery[parserState.pos]) !== -1) { - let endChar = ")"; - let name = "()"; - let friendlyName = "tuple"; - - if (parserState.userQuery[parserState.pos] === "[") { - endChar = "]"; - name = "[]"; - friendlyName = "slice"; + getItemsBefore(query, parserState, generics, ">"); + } else if (parserState.pos < parserState.length && + parserState.userQuery[parserState.pos] === "(" + ) { + if (start >= end) { + throw ["Found generics without a path"]; + } + if (parserState.isInBinding) { + throw ["Unexpected ", "(", " after ", "="]; } parserState.pos += 1; - const { foundSeparator } = getItemsBefore(query, parserState, generics, endChar); const typeFilter = parserState.typeFilter; - const bindingName = parserState.isInBinding; parserState.typeFilter = null; - parserState.isInBinding = null; - for (const gen of generics) { - if (gen.bindingName !== null) { - throw ["Type parameter ", "=", ` cannot be within ${friendlyName} `, name]; - } - } - if (name === "()" && !foundSeparator && generics.length === 1 && typeFilter === null) { - elems.push(generics[0]); - } else if (name === "()" && generics.length === 1 && generics[0].name === "->") { - // `primitive:(a -> b)` parser to `primitive:"->"<output=b, (a,)>` - // not `primitive:"()"<"->"<output=b, (a,)>>` - generics[0].typeFilter = typeFilter; - elems.push(generics[0]); + getItemsBefore(query, parserState, generics, ")"); + skipWhitespace(parserState); + if (isReturnArrow(parserState)) { + parserState.pos += 2; + skipWhitespace(parserState); + getFilteredNextElem(query, parserState, generics, isInGenerics); + generics[generics.length - 1].bindingName = makePrimitiveElement("output"); } else { - if (typeFilter !== null && typeFilter !== "primitive") { - throw [ - "Invalid search type: primitive ", - name, - " and ", - typeFilter, - " both specified", - ]; - } - parserState.totalElems += 1; - if (isInGenerics) { - parserState.genericsElems += 1; - } - elems.push(makePrimitiveElement(name, { bindingName, generics })); + generics.push(makePrimitiveElement(null, { + bindingName: makePrimitiveElement("output"), + typeFilter: null, + })); } - } else if (parserState.userQuery[parserState.pos] === "&") { - if (parserState.typeFilter !== null && parserState.typeFilter !== "primitive") { - throw [ - "Invalid search type: primitive ", - "&", - " and ", - parserState.typeFilter, - " both specified", - ]; + parserState.typeFilter = typeFilter; + } + if (isStringElem) { + skipWhitespace(parserState); + } + if (start >= end && generics.length === 0) { + return; + } + if (parserState.userQuery[parserState.pos] === "=") { + if (parserState.isInBinding) { + throw ["Cannot write ", "=", " twice in a binding"]; } - parserState.typeFilter = null; - parserState.pos += 1; - let c = parserState.userQuery[parserState.pos]; - while (c === " " && parserState.pos < parserState.length) { - parserState.pos += 1; - c = parserState.userQuery[parserState.pos]; + if (!isInGenerics) { + throw ["Type parameter ", "=", " must be within generics list"]; } - const generics = []; - if (parserState.userQuery.slice(parserState.pos, parserState.pos + 3) === "mut") { - generics.push(makePrimitiveElement("mut", { typeFilter: "keyword"})); - parserState.pos += 3; - c = parserState.userQuery[parserState.pos]; + const name = parserState.userQuery.slice(start, end).trim(); + if (name === "!") { + throw ["Type parameter ", "=", " key cannot be ", "!", " never type"]; } - while (c === " " && parserState.pos < parserState.length) { - parserState.pos += 1; - c = parserState.userQuery[parserState.pos]; + if (name.includes("!")) { + throw ["Type parameter ", "=", " key cannot be ", "!", " macro"]; } - if (!isEndCharacter(c) && parserState.pos < parserState.length) { - getFilteredNextElem(query, parserState, generics, isInGenerics); + if (name.includes("::")) { + throw ["Type parameter ", "=", " key cannot contain ", "::", " path"]; } - elems.push(makePrimitiveElement("reference", { generics })); + if (name.includes(":")) { + throw ["Type parameter ", "=", " key cannot contain ", ":", " type"]; + } + parserState.isInBinding = { name, generics }; } else { - const isStringElem = parserState.userQuery[start] === "\""; - // We handle the strings on their own mostly to make code easier to follow. - if (isStringElem) { - start += 1; - getStringElem(query, parserState, isInGenerics); - end = parserState.pos - 1; - } else { - end = getIdentEndPosition(parserState); + elems.push( + createQueryElement( + query, + parserState, + parserState.userQuery.slice(start, end), + generics, + isInGenerics, + ), + ); + } + } +} + +/** + * Checks that the type filter doesn't have unwanted characters like `<>` (which are ignored + * if empty). + * + * @param {ParserState} parserState + */ +function checkExtraTypeFilterCharacters(start, parserState) { + const query = parserState.userQuery.slice(start, parserState.pos).trim(); + + const match = query.match(REGEX_INVALID_TYPE_FILTER); + if (match) { + throw [ + "Unexpected ", + match[0], + " in type filter (before ", + ":", + ")", + ]; + } +} + +/** + * @param {ParsedQuery} query + * @param {ParserState} parserState + * @param {string} name - Name of the query element. + * @param {Array<QueryElement>} generics - List of generics of this query element. + * + * @return {QueryElement} - The newly created `QueryElement`. + */ +function createQueryElement(query, parserState, name, generics, isInGenerics) { + const path = name.trim(); + if (path.length === 0 && generics.length === 0) { + throw ["Unexpected ", parserState.userQuery[parserState.pos]]; + } + if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { + throw ["Cannot have more than one element if you use quotes"]; + } + const typeFilter = parserState.typeFilter; + parserState.typeFilter = null; + if (name === "!") { + if (typeFilter !== null && typeFilter !== "primitive") { + throw [ + "Invalid search type: primitive never type ", + "!", + " and ", + typeFilter, + " both specified", + ]; + } + if (generics.length !== 0) { + throw [ + "Never type ", + "!", + " does not accept generic parameters", + ]; + } + const bindingName = parserState.isInBinding; + parserState.isInBinding = null; + return makePrimitiveElement("never", { bindingName }); + } + const quadcolon = /::\s*::/.exec(path); + if (path.startsWith("::")) { + throw ["Paths cannot start with ", "::"]; + } else if (path.endsWith("::")) { + throw ["Paths cannot end with ", "::"]; + } else if (quadcolon !== null) { + throw ["Unexpected ", quadcolon[0]]; + } + const pathSegments = path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/); + // In case we only have something like `<p>`, there is no name. + if (pathSegments.length === 0 + || (pathSegments.length === 1 && pathSegments[0] === "")) { + if (generics.length > 0 || prevIs(parserState, ">")) { + throw ["Found generics without a path"]; + } else { + throw ["Unexpected ", parserState.userQuery[parserState.pos]]; + } + } + for (const [i, pathSegment] of pathSegments.entries()) { + if (pathSegment === "!") { + if (i !== 0) { + throw ["Never type ", "!", " is not associated item"]; } - if (parserState.pos < parserState.length && - parserState.userQuery[parserState.pos] === "<" - ) { - if (start >= end) { - throw ["Found generics without a path"]; - } - parserState.pos += 1; - getItemsBefore(query, parserState, generics, ">"); - } else if (parserState.pos < parserState.length && - parserState.userQuery[parserState.pos] === "(" - ) { - if (start >= end) { - throw ["Found generics without a path"]; - } - if (parserState.isInBinding) { - throw ["Unexpected ", "(", " after ", "="]; - } + pathSegments[i] = "never"; + } + } + parserState.totalElems += 1; + if (isInGenerics) { + parserState.genericsElems += 1; + } + const bindingName = parserState.isInBinding; + parserState.isInBinding = null; + const bindings = new Map(); + const pathLast = pathSegments[pathSegments.length - 1]; + return { + name: name.trim(), + id: null, + fullPath: pathSegments, + pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1), + pathLast, + normalizedPathLast: pathLast.replace(/_/g, ""), + generics: generics.filter(gen => { + // Syntactically, bindings are parsed as generics, + // but the query engine treats them differently. + if (gen.bindingName !== null) { + if (gen.name !== null) { + gen.bindingName.generics.unshift(gen); + } + bindings.set(gen.bindingName.name, gen.bindingName.generics); + return false; + } + return true; + }), + bindings, + typeFilter, + bindingName, + }; +} + +function makePrimitiveElement(name, extra) { + return Object.assign({ + name, + id: null, + fullPath: [name], + pathWithoutLast: [], + pathLast: name, + normalizedPathLast: name, + generics: [], + bindings: new Map(), + typeFilter: "primitive", + bindingName: null, + }, extra); +} + +/** + * If we encounter a `"`, then we try to extract the string + * from it until we find another `"`. + * + * This function will throw an error in the following cases: + * * There is already another string element. + * * We are parsing a generic argument. + * * There is more than one element. + * * There is no closing `"`. + * + * @param {ParsedQuery} query + * @param {ParserState} parserState + * @param {boolean} isInGenerics + */ +function getStringElem(query, parserState, isInGenerics) { + if (isInGenerics) { + throw ["Unexpected ", "\"", " in generics"]; + } else if (query.literalSearch) { + throw ["Cannot have more than one literal search element"]; + } else if (parserState.totalElems - parserState.genericsElems > 0) { + throw ["Cannot use literal search when there is more than one element"]; + } + parserState.pos += 1; + const start = parserState.pos; + const end = getIdentEndPosition(parserState); + if (parserState.pos >= parserState.length) { + throw ["Unclosed ", "\""]; + } else if (parserState.userQuery[end] !== "\"") { + throw ["Unexpected ", parserState.userQuery[end], " in a string element"]; + } else if (start === end) { + throw ["Cannot have empty string element"]; + } + // To skip the quote at the end. + parserState.pos += 1; + query.literalSearch = true; +} + +/** + * This function goes through all characters until it reaches an invalid ident + * character or the end of the query. It returns the position of the last + * character of the ident. + * + * @param {ParserState} parserState + * + * @return {integer} + */ +function getIdentEndPosition(parserState) { + let afterIdent = consumeIdent(parserState); + let end = parserState.pos; + let macroExclamation = -1; + while (parserState.pos < parserState.length) { + const c = parserState.userQuery[parserState.pos]; + if (c === "!") { + if (macroExclamation !== -1) { + throw ["Cannot have more than one ", "!", " in an ident"]; + } else if (parserState.pos + 1 < parserState.length) { + const pos = parserState.pos; + parserState.pos++; + const beforeIdent = consumeIdent(parserState); + parserState.pos = pos; + if (beforeIdent) { + throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; + } + } + if (afterIdent) macroExclamation = parserState.pos; + } else if (isPathSeparator(c)) { + if (c === ":") { + if (!isPathStart(parserState)) { + break; + } + // Skip current ":". parserState.pos += 1; - const typeFilter = parserState.typeFilter; - parserState.typeFilter = null; - getItemsBefore(query, parserState, generics, ")"); - skipWhitespace(parserState); - if (isReturnArrow(parserState)) { - parserState.pos += 2; - skipWhitespace(parserState); - getFilteredNextElem(query, parserState, generics, isInGenerics); - generics[generics.length - 1].bindingName = makePrimitiveElement("output"); - } else { - generics.push(makePrimitiveElement(null, { - bindingName: makePrimitiveElement("output"), - typeFilter: null, - })); + } else { + while (parserState.pos + 1 < parserState.length) { + const next_c = parserState.userQuery[parserState.pos + 1]; + if (next_c !== " ") { + break; + } + parserState.pos += 1; } - parserState.typeFilter = typeFilter; - } - if (isStringElem) { - skipWhitespace(parserState); - } - if (start >= end && generics.length === 0) { - return; } - if (parserState.userQuery[parserState.pos] === "=") { - if (parserState.isInBinding) { - throw ["Cannot write ", "=", " twice in a binding"]; - } - if (!isInGenerics) { - throw ["Type parameter ", "=", " must be within generics list"]; - } - const name = parserState.userQuery.slice(start, end).trim(); - if (name === "!") { - throw ["Type parameter ", "=", " key cannot be ", "!", " never type"]; - } - if (name.includes("!")) { - throw ["Type parameter ", "=", " key cannot be ", "!", " macro"]; - } - if (name.includes("::")) { - throw ["Type parameter ", "=", " key cannot contain ", "::", " path"]; - } - if (name.includes(":")) { - throw ["Type parameter ", "=", " key cannot contain ", ":", " type"]; - } - parserState.isInBinding = { name, generics }; - } else { - elems.push( - createQueryElement( - query, - parserState, - parserState.userQuery.slice(start, end), - generics, - isInGenerics, - ), - ); + if (macroExclamation !== -1) { + throw ["Cannot have associated items in macros"]; } + } else if ( + c === "[" || + c === "(" || + isEndCharacter(c) || + isSpecialStartCharacter(c) || + isSeparatorCharacter(c) + ) { + break; + } else if (parserState.pos > 0) { + throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1], + " (not a valid identifier)"]; + } else { + throw ["Unexpected ", c, " (not a valid identifier)"]; + } + parserState.pos += 1; + afterIdent = consumeIdent(parserState); + end = parserState.pos; + } + if (macroExclamation !== -1) { + if (parserState.typeFilter === null) { + parserState.typeFilter = "macro"; + } else if (parserState.typeFilter !== "macro") { + throw [ + "Invalid search type: macro ", + "!", + " and ", + parserState.typeFilter, + " both specified", + ]; } + end = macroExclamation; } + return end; +} - /** - * This function parses the next query element until it finds `endChar`, calling `getNextElem` - * to collect each element. - * - * If there is no `endChar`, this function will implicitly stop at the end without raising an - * error. - * - * @param {ParsedQuery} query - * @param {ParserState} parserState - * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added. - * @param {string} endChar - This function will stop when it'll encounter this - * character. - * @returns {{foundSeparator: bool}} - */ - function getItemsBefore(query, parserState, elems, endChar) { - let foundStopChar = true; - let foundSeparator = false; +function isSpecialStartCharacter(c) { + return "<\"".indexOf(c) !== -1; +} - // If this is a generic, keep the outer item's type filter around. - const oldTypeFilter = parserState.typeFilter; - parserState.typeFilter = null; - const oldIsInBinding = parserState.isInBinding; - parserState.isInBinding = null; +/** + * Returns `true` if the current parser position is starting with "::". + * + * @param {ParserState} parserState + * + * @return {boolean} + */ +function isPathStart(parserState) { + return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) === "::"; +} - // ML-style Higher Order Function notation - // - // a way to search for any closure or fn pointer regardless of - // which closure trait is used - // - // Looks like this: - // - // `option<t>, (t -> u) -> option<u>` - // ^^^^^^ - // - // The Rust-style closure notation is implemented in getNextElem - let hofParameters = null; - - let extra = ""; - if (endChar === ">") { - extra = "<"; - } else if (endChar === "]") { - extra = "["; - } else if (endChar === ")") { - extra = "("; - } else if (endChar === "") { - extra = "->"; - } else { - extra = endChar; - } +/** + * If the current parser position is at the beginning of an identifier, + * move the position to the end of it and return `true`. Otherwise, return `false`. + * + * @param {ParserState} parserState + * + * @return {boolean} + */ +function consumeIdent(parserState) { + REGEX_IDENT.lastIndex = parserState.pos; + const match = parserState.userQuery.match(REGEX_IDENT); + if (match) { + parserState.pos += match[0].length; + return true; + } + return false; +} - while (parserState.pos < parserState.length) { - const c = parserState.userQuery[parserState.pos]; - if (c === endChar) { - if (parserState.isInBinding) { - throw ["Unexpected ", endChar, " after ", "="]; - } - break; - } else if (endChar !== "" && isReturnArrow(parserState)) { - // ML-style HOF notation only works when delimited in something, - // otherwise a function arrow starts the return type of the top - if (parserState.isInBinding) { - throw ["Unexpected ", "->", " after ", "="]; - } - hofParameters = [...elems]; - elems.length = 0; - parserState.pos += 2; - foundStopChar = true; - foundSeparator = false; - continue; - } else if (c === " ") { - parserState.pos += 1; - continue; - } else if (isSeparatorCharacter(c)) { - parserState.pos += 1; - foundStopChar = true; - foundSeparator = true; - continue; - } else if (c === ":" && isPathStart(parserState)) { - throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; - } else if (isEndCharacter(c)) { - throw ["Unexpected ", c, " after ", extra]; - } - if (!foundStopChar) { - let extra = []; - if (isLastElemGeneric(query.elems, parserState)) { - extra = [" after ", ">"]; - } else if (prevIs(parserState, "\"")) { - throw ["Cannot have more than one element if you use quotes"]; - } - if (endChar !== "") { - throw [ - "Expected ", - ",", - ", ", - "=", - ", or ", - endChar, - ...extra, - ", found ", - c, - ]; - } - throw [ - "Expected ", - ",", - " or ", - "=", - ...extra, - ", found ", - c, - ]; +/** + * Returns `true` if the given `c` character is a path separator. For example + * `:` in `a::b` or a whitespace in `a b`. + * + * @param {string} c + * + * @return {boolean} + */ +function isPathSeparator(c) { + return c === ":" || c === " "; +} + +class VlqHexDecoder { + constructor(string, cons) { + this.string = string; + this.cons = cons; + this.offset = 0; + this.backrefQueue = []; + } + // call after consuming `{` + decodeList() { + let c = this.string.charCodeAt(this.offset); + const ret = []; + while (c !== 125) { // 125 = "}" + ret.push(this.decode()); + c = this.string.charCodeAt(this.offset); + } + this.offset += 1; // eat cb + return ret; + } + // consumes and returns a list or integer + decode() { + let n = 0; + let c = this.string.charCodeAt(this.offset); + if (c === 123) { // 123 = "{" + this.offset += 1; + return this.decodeList(); + } + while (c < 96) { // 96 = "`" + n = (n << 4) | (c & 0xF); + this.offset += 1; + c = this.string.charCodeAt(this.offset); + } + // last character >= la + n = (n << 4) | (c & 0xF); + const [sign, value] = [n & 1, n >> 1]; + this.offset += 1; + return sign ? -value : value; + } + next() { + const c = this.string.charCodeAt(this.offset); + // sixteen characters after "0" are backref + if (c >= 48 && c < 64) { // 48 = "0", 64 = "@" + this.offset += 1; + return this.backrefQueue[c - 48]; + } + // special exception: 0 doesn't use backref encoding + // it's already one character, and it's always nullish + if (c === 96) { // 96 = "`" + this.offset += 1; + return this.cons(0); + } + const result = this.cons(this.decode()); + this.backrefQueue.unshift(result); + if (this.backrefQueue.length > 16) { + this.backrefQueue.pop(); + } + return result; + } +} +class RoaringBitmap { + constructor(str) { + const strdecoded = atob(str); + const u8array = new Uint8Array(strdecoded.length); + for (let j = 0; j < strdecoded.length; ++j) { + u8array[j] = strdecoded.charCodeAt(j); + } + const has_runs = u8array[0] === 0x3b; + const size = has_runs ? + ((u8array[2] | (u8array[3] << 8)) + 1) : + ((u8array[4] | (u8array[5] << 8) | (u8array[6] << 16) | (u8array[7] << 24))); + let i = has_runs ? 4 : 8; + let is_run; + if (has_runs) { + const is_run_len = Math.floor((size + 7) / 8); + is_run = u8array.slice(i, i + is_run_len); + i += is_run_len; + } else { + is_run = new Uint8Array(); + } + this.keys = []; + this.cardinalities = []; + for (let j = 0; j < size; ++j) { + this.keys.push(u8array[i] | (u8array[i + 1] << 8)); + i += 2; + this.cardinalities.push((u8array[i] | (u8array[i + 1] << 8)) + 1); + i += 2; + } + this.containers = []; + let offsets = null; + if (!has_runs || this.keys.length >= 4) { + offsets = []; + for (let j = 0; j < size; ++j) { + offsets.push(u8array[i] | (u8array[i + 1] << 8) | (u8array[i + 2] << 16) | + (u8array[i + 3] << 24)); + i += 4; } - const posBefore = parserState.pos; - getFilteredNextElem(query, parserState, elems, endChar !== ""); - if (endChar !== "" && parserState.pos >= parserState.length) { - throw ["Unclosed ", extra]; + } + for (let j = 0; j < size; ++j) { + if (offsets && offsets[j] !== i) { + console.log(this.containers); + throw new Error(`corrupt bitmap ${j}: ${i} / ${offsets[j]}`); } - // This case can be encountered if `getNextElem` encountered a "stop character" right - // from the start. For example if you have `,,` or `<>`. In this case, we simply move up - // the current position to continue the parsing. - if (posBefore === parserState.pos) { - parserState.pos += 1; + if (is_run[j >> 3] & (1 << (j & 0x7))) { + const runcount = (u8array[i] | (u8array[i + 1] << 8)); + i += 2; + this.containers.push(new RoaringBitmapRun( + runcount, + u8array.slice(i, i + (runcount * 4)), + )); + i += runcount * 4; + } else if (this.cardinalities[j] >= 4096) { + this.containers.push(new RoaringBitmapBits(u8array.slice(i, i + 8192))); + i += 8192; + } else { + const end = this.cardinalities[j] * 2; + this.containers.push(new RoaringBitmapArray( + this.cardinalities[j], + u8array.slice(i, i + end), + )); + i += end; } - foundStopChar = false; } - if (parserState.pos >= parserState.length && endChar !== "") { - throw ["Unclosed ", extra]; + } + contains(keyvalue) { + const key = keyvalue >> 16; + const value = keyvalue & 0xFFFF; + for (let i = 0; i < this.keys.length; ++i) { + if (this.keys[i] === key) { + return this.containers[i].contains(value); + } } - // We are either at the end of the string or on the `endChar` character, let's move forward - // in any case. - parserState.pos += 1; + return false; + } +} - if (hofParameters) { - // Commas in a HOF don't cause wrapping parens to become a tuple. - // If you want a one-tuple with a HOF in it, write `((a -> b),)`. - foundSeparator = false; - // HOFs can't have directly nested bindings. - if ([...elems, ...hofParameters].some(x => x.bindingName) || parserState.isInBinding) { - throw ["Unexpected ", "=", " within ", "->"]; - } - // HOFs are represented the same way closures are. - // The arguments are wrapped in a tuple, and the output - // is a binding, even though the compiler doesn't technically - // represent fn pointers that way. - const hofElem = makePrimitiveElement("->", { - generics: hofParameters, - bindings: new Map([["output", [...elems]]]), - typeFilter: null, - }); - elems.length = 0; - elems[0] = hofElem; +class RoaringBitmapRun { + constructor(runcount, array) { + this.runcount = runcount; + this.array = array; + } + contains(value) { + const l = this.runcount * 4; + for (let i = 0; i < l; i += 4) { + const start = this.array[i] | (this.array[i + 1] << 8); + const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8); + if (value >= start && value <= (start + lenm1)) { + return true; + } } + return false; + } +} +class RoaringBitmapArray { + constructor(cardinality, array) { + this.cardinality = cardinality; + this.array = array; + } + contains(value) { + const l = this.cardinality * 2; + for (let i = 0; i < l; i += 2) { + const start = this.array[i] | (this.array[i + 1] << 8); + if (value === start) { + return true; + } + } + return false; + } +} +class RoaringBitmapBits { + constructor(array) { + this.array = array; + } + contains(value) { + return !!(this.array[value >> 3] & (1 << (value & 7))); + } +} + + +class DocSearch { + constructor(rawSearchIndex, rootPath, searchState) { + /** + * @type {Map<String, RoaringBitmap>} + */ + this.searchIndexDeprecated = new Map(); + /** + * @type {Map<String, RoaringBitmap>} + */ + this.searchIndexEmptyDesc = new Map(); + /** + * @type {Uint32Array} + */ + this.functionTypeFingerprint = null; + /** + * Map from normalized type names to integers. Used to make type search + * more efficient. + * + * @type {Map<string, {id: integer, assocOnly: boolean}>} + */ + this.typeNameIdMap = new Map(); + this.ALIASES = new Map(); + this.rootPath = rootPath; + this.searchState = searchState; + + /** + * Special type name IDs for searching by array. + */ + this.typeNameIdOfArray = this.buildTypeMapIndex("array"); + /** + * Special type name IDs for searching by slice. + */ + this.typeNameIdOfSlice = this.buildTypeMapIndex("slice"); + /** + * Special type name IDs for searching by both array and slice (`[]` syntax). + */ + this.typeNameIdOfArrayOrSlice = this.buildTypeMapIndex("[]"); + /** + * Special type name IDs for searching by tuple. + */ + this.typeNameIdOfTuple = this.buildTypeMapIndex("tuple"); + /** + * Special type name IDs for searching by unit. + */ + this.typeNameIdOfUnit = this.buildTypeMapIndex("unit"); + /** + * Special type name IDs for searching by both tuple and unit (`()` syntax). + */ + this.typeNameIdOfTupleOrUnit = this.buildTypeMapIndex("()"); + /** + * Special type name IDs for searching `fn`. + */ + this.typeNameIdOfFn = this.buildTypeMapIndex("fn"); + /** + * Special type name IDs for searching `fnmut`. + */ + this.typeNameIdOfFnMut = this.buildTypeMapIndex("fnmut"); + /** + * Special type name IDs for searching `fnonce`. + */ + this.typeNameIdOfFnOnce = this.buildTypeMapIndex("fnonce"); + /** + * Special type name IDs for searching higher order functions (`->` syntax). + */ + this.typeNameIdOfHof = this.buildTypeMapIndex("->"); + + /** + * Empty, immutable map used in item search types with no bindings. + * + * @type {Map<number, Array<FunctionType>>} + */ + this.EMPTY_BINDINGS_MAP = new Map(); - parserState.typeFilter = oldTypeFilter; - parserState.isInBinding = oldIsInBinding; + /** + * Empty, immutable map used in item search types with no bindings. + * + * @type {Array<FunctionType>} + */ + this.EMPTY_GENERICS_ARRAY = []; + + /** + * Object pool for function types with no bindings or generics. + * This is reset after loading the index. + * + * @type {Map<number|null, FunctionType>} + */ + this.TYPES_POOL = new Map(); - return { foundSeparator }; + /** + * @type {Array<Row>} + */ + this.searchIndex = this.buildIndex(rawSearchIndex); } /** - * Checks that the type filter doesn't have unwanted characters like `<>` (which are ignored - * if empty). + * Add an item to the type Name->ID map, or, if one already exists, use it. + * Returns the number. If name is "" or null, return null (pure generic). + * + * This is effectively string interning, so that function matching can be + * done more quickly. Two types with the same name but different item kinds + * get the same ID. * - * @param {ParserState} parserState + * @param {string} name + * @param {boolean} isAssocType - True if this is an assoc type + * + * @returns {integer} */ - function checkExtraTypeFilterCharacters(start, parserState) { - const query = parserState.userQuery.slice(start, parserState.pos).trim(); + buildTypeMapIndex(name, isAssocType) { + if (name === "" || name === null) { + return null; + } - const match = query.match(REGEX_INVALID_TYPE_FILTER); - if (match) { - throw [ - "Unexpected ", - match[0], - " in type filter (before ", - ":", - ")", - ]; + if (this.typeNameIdMap.has(name)) { + const obj = this.typeNameIdMap.get(name); + obj.assocOnly = isAssocType && obj.assocOnly; + return obj.id; + } else { + const id = this.typeNameIdMap.size; + this.typeNameIdMap.set(name, { id, assocOnly: isAssocType }); + return id; } } /** - * Parses the provided `query` input to fill `parserState`. If it encounters an error while - * parsing `query`, it'll throw an error. + * Convert a list of RawFunctionType / ID to object-based FunctionType. + * + * Crates often have lots of functions in them, and it's common to have a large number of + * functions that operate on a small set of data types, so the search index compresses them + * by encoding function parameter and return types as indexes into an array of names. * - * @param {ParsedQuery} query - * @param {ParserState} parserState + * Even when a general-purpose compression algorithm is used, this is still a win. + * I checked. https://github.com/rust-lang/rust/pull/98475#issue-1284395985 + * + * The format for individual function types is encoded in + * librustdoc/html/render/mod.rs: impl Serialize for RenderType + * + * @param {null|Array<RawFunctionType>} types + * @param {Array<{name: string, ty: number}>} lowercasePaths + * + * @return {Array<FunctionSearchType>} */ - function parseInput(query, parserState) { - let foundStopChar = true; - - while (parserState.pos < parserState.length) { - const c = parserState.userQuery[parserState.pos]; - if (isEndCharacter(c)) { - foundStopChar = true; - if (isSeparatorCharacter(c)) { - parserState.pos += 1; - continue; - } else if (c === "-" || c === ">") { - if (isReturnArrow(parserState)) { - break; - } - throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; - } else if (parserState.pos > 0) { - throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]]; - } - throw ["Unexpected ", c]; - } else if (c === " ") { - skipWhitespace(parserState); - continue; - } - if (!foundStopChar) { - let extra = ""; - if (isLastElemGeneric(query.elems, parserState)) { - extra = [" after ", ">"]; - } else if (prevIs(parserState, "\"")) { - throw ["Cannot have more than one element if you use quotes"]; - } - if (parserState.typeFilter !== null) { - throw [ - "Expected ", - ",", - " or ", - "->", - ...extra, - ", found ", - c, + buildItemSearchTypeAll(types, lowercasePaths) { + return types.length > 0 ? + types.map(type => this.buildItemSearchType(type, lowercasePaths)) : + this.EMPTY_GENERICS_ARRAY; + } + + /** + * Converts a single type. + * + * @param {RawFunctionType} type + */ + buildItemSearchType(type, lowercasePaths, isAssocType) { + const PATH_INDEX_DATA = 0; + const GENERICS_DATA = 1; + const BINDINGS_DATA = 2; + let pathIndex, generics, bindings; + if (typeof type === "number") { + pathIndex = type; + generics = this.EMPTY_GENERICS_ARRAY; + bindings = this.EMPTY_BINDINGS_MAP; + } else { + pathIndex = type[PATH_INDEX_DATA]; + generics = this.buildItemSearchTypeAll( + type[GENERICS_DATA], + lowercasePaths, + ); + if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) { + bindings = new Map(type[BINDINGS_DATA].map(binding => { + const [assocType, constraints] = binding; + // Associated type constructors are represented sloppily in rustdoc's + // type search, to make the engine simpler. + // + // MyType<Output<T>=Result<T>> is equivalent to MyType<Output<Result<T>>=T> + // and both are, essentially + // MyType<Output=(T, Result<T>)>, except the tuple isn't actually there. + // It's more like the value of a type binding is naturally an array, + // which rustdoc calls "constraints". + // + // As a result, the key should never have generics on it. + return [ + this.buildItemSearchType(assocType, lowercasePaths, true).id, + this.buildItemSearchTypeAll(constraints, lowercasePaths), ]; - } - throw [ - "Expected ", - ",", - ", ", - ":", - " or ", - "->", - ...extra, - ", found ", - c, - ]; - } - const before = query.elems.length; - getFilteredNextElem(query, parserState, query.elems, false); - if (query.elems.length === before) { - // Nothing was added, weird... Let's increase the position to not remain stuck. - parserState.pos += 1; + })); + } else { + bindings = this.EMPTY_BINDINGS_MAP; } - foundStopChar = false; } - if (parserState.typeFilter !== null) { - throw [ - "Unexpected ", - ":", - " (expected path after type filter ", - parserState.typeFilter + ":", - ")", - ]; + /** + * @type {FunctionType} + */ + let result; + if (pathIndex < 0) { + // types less than 0 are generic parameters + // the actual names of generic parameters aren't stored, since they aren't API + result = { + id: pathIndex, + ty: TY_GENERIC, + path: null, + exactPath: null, + generics, + bindings, + }; + } else if (pathIndex === 0) { + // `0` is used as a sentinel because it's fewer bytes than `null` + result = { + id: null, + ty: null, + path: null, + exactPath: null, + generics, + bindings, + }; + } else { + const item = lowercasePaths[pathIndex - 1]; + result = { + id: this.buildTypeMapIndex(item.name, isAssocType), + ty: item.ty, + path: item.path, + exactPath: item.exactPath, + generics, + bindings, + }; } - while (parserState.pos < parserState.length) { - if (isReturnArrow(parserState)) { - parserState.pos += 2; - skipWhitespace(parserState); - // Get returned elements. - getItemsBefore(query, parserState, query.returned, ""); - // Nothing can come afterward! - if (query.returned.length === 0) { - throw ["Expected at least one item after ", "->"]; + const cr = this.TYPES_POOL.get(result.id); + if (cr) { + // Shallow equality check. Since this function is used + // to construct every type object, this should be mostly + // equivalent to a deep equality check, except if there's + // a conflict, we don't keep the old one around, so it's + // not a fully precise implementation of hashcons. + if (cr.generics.length === result.generics.length && + cr.generics !== result.generics && + cr.generics.every((x, i) => result.generics[i] === x) + ) { + result.generics = cr.generics; + } + if (cr.bindings.size === result.bindings.size && cr.bindings !== result.bindings) { + let ok = true; + for (const [k, v] of cr.bindings.entries()) { + const v2 = result.bindings.get(v); + if (!v2) { + ok = false; + break; + } + if (v !== v2 && v.length === v2.length && v.every((x, i) => v2[i] === x)) { + result.bindings.set(k, v); + } else if (v !== v2) { + ok = false; + break; + } + } + if (ok) { + result.bindings = cr.bindings; } - break; - } else { - parserState.pos += 1; + } + if (cr.ty === result.ty && cr.path === result.path + && cr.bindings === result.bindings && cr.generics === result.generics + && cr.ty === result.ty + ) { + return cr; } } + this.TYPES_POOL.set(result.id, result); + return result; } /** - * Takes the user search input and returns an empty `ParsedQuery`. + * Type fingerprints allow fast, approximate matching of types. * - * @param {string} userQuery + * This algo creates a compact representation of the type set using a Bloom filter. + * This fingerprint is used three ways: + * + * - It accelerates the matching algorithm by checking the function fingerprint against the + * query fingerprint. If any bits are set in the query but not in the function, it can't + * match. + * + * - The fourth section has the number of distinct items in the set. + * This is the distance function, used for filtering and for sorting. * - * @return {ParsedQuery} + * [^1]: Distance is the relatively naive metric of counting the number of distinct items in + * the function that are not present in the query. + * + * @param {FunctionType|QueryElement} type - a single type + * @param {Uint32Array} output - write the fingerprint to this data structure: uses 128 bits + * @param {Set<number>} fps - Set of distinct items */ - function newParsedQuery(userQuery) { - return { - original: userQuery, - userQuery: userQuery.toLowerCase(), - elems: [], - returned: [], - // Total number of "top" elements (does not include generics). - foundElems: 0, - // Total number of elements (includes generics). - totalElems: 0, - literalSearch: false, - error: null, - correction: null, - proposeCorrectionFrom: null, - proposeCorrectionTo: null, - // bloom filter build from type ids - typeFingerprint: new Uint32Array(4), + buildFunctionTypeFingerprint(type, output, fps) { + let input = type.id; + // All forms of `[]`/`()`/`->` get collapsed down to one thing in the bloom filter. + // Differentiating between arrays and slices, if the user asks for it, is + // still done in the matching algorithm. + if (input === this.typeNameIdOfArray || input === this.typeNameIdOfSlice) { + input = this.typeNameIdOfArrayOrSlice; + } + if (input === this.typeNameIdOfTuple || input === this.typeNameIdOfUnit) { + input = this.typeNameIdOfTupleOrUnit; + } + if (input === this.typeNameIdOfFn || input === this.typeNameIdOfFnMut || + input === this.typeNameIdOfFnOnce) { + input = this.typeNameIdOfHof; + } + // http://burtleburtle.net/bob/hash/integer.html + // ~~ is toInt32. It's used before adding, so + // the number stays in safe integer range. + const hashint1 = k => { + k = (~~k + 0x7ed55d16) + (k << 12); + k = (k ^ 0xc761c23c) ^ (k >>> 19); + k = (~~k + 0x165667b1) + (k << 5); + k = (~~k + 0xd3a2646c) ^ (k << 9); + k = (~~k + 0xfd7046c5) + (k << 3); + return (k ^ 0xb55a4f09) ^ (k >>> 16); + }; + const hashint2 = k => { + k = ~k + (k << 15); + k ^= k >>> 12; + k += k << 2; + k ^= k >>> 4; + k = Math.imul(k, 2057); + return k ^ (k >> 16); }; + if (input !== null) { + const h0a = hashint1(input); + const h0b = hashint2(input); + // Less Hashing, Same Performance: Building a Better Bloom Filter + // doi=10.1.1.72.2442 + const h1a = ~~(h0a + Math.imul(h0b, 2)); + const h1b = ~~(h0a + Math.imul(h0b, 3)); + const h2a = ~~(h0a + Math.imul(h0b, 4)); + const h2b = ~~(h0a + Math.imul(h0b, 5)); + output[0] |= (1 << (h0a % 32)) | (1 << (h1b % 32)); + output[1] |= (1 << (h1a % 32)) | (1 << (h2b % 32)); + output[2] |= (1 << (h2a % 32)) | (1 << (h0b % 32)); + fps.add(input); + } + for (const g of type.generics) { + this.buildFunctionTypeFingerprint(g, output, fps); + } + const fb = { + id: null, + ty: 0, + generics: this.EMPTY_GENERICS_ARRAY, + bindings: this.EMPTY_BINDINGS_MAP, + }; + for (const [k, v] of type.bindings.entries()) { + fb.id = k; + fb.generics = v; + this.buildFunctionTypeFingerprint(fb, output, fps); + } + output[3] = fps.size; } /** - * Build an URL with search parameters. - * - * @param {string} search - The current search being performed. - * @param {string|null} filterCrates - The current filtering crate (if any). + * Convert raw search index into in-memory search index. * - * @return {string} + * @param {[string, RawSearchIndexCrate][]} rawSearchIndex */ - function buildUrl(search, filterCrates) { - let extra = "?search=" + encodeURIComponent(search); + buildIndex(rawSearchIndex) { + /** + * Convert from RawFunctionSearchType to FunctionSearchType. + * + * Crates often have lots of functions in them, and function signatures are sometimes + * complex, so rustdoc uses a pretty tight encoding for them. This function converts it + * to a simpler, object-based encoding so that the actual search code is more readable + * and easier to debug. + * + * The raw function search type format is generated using serde in + * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string + * + * @param {Array<{name: string, ty: number}>} lowercasePaths + * + * @return {null|FunctionSearchType} + */ + const buildFunctionSearchTypeCallback = lowercasePaths => { + return functionSearchType => { + if (functionSearchType === 0) { + return null; + } + const INPUTS_DATA = 0; + const OUTPUT_DATA = 1; + let inputs, output; + if (typeof functionSearchType[INPUTS_DATA] === "number") { + inputs = [ + this.buildItemSearchType(functionSearchType[INPUTS_DATA], lowercasePaths), + ]; + } else { + inputs = this.buildItemSearchTypeAll( + functionSearchType[INPUTS_DATA], + lowercasePaths, + ); + } + if (functionSearchType.length > 1) { + if (typeof functionSearchType[OUTPUT_DATA] === "number") { + output = [ + this.buildItemSearchType( + functionSearchType[OUTPUT_DATA], + lowercasePaths, + ), + ]; + } else { + output = this.buildItemSearchTypeAll( + functionSearchType[OUTPUT_DATA], + lowercasePaths, + ); + } + } else { + output = []; + } + const where_clause = []; + const l = functionSearchType.length; + for (let i = 2; i < l; ++i) { + where_clause.push(typeof functionSearchType[i] === "number" + ? [this.buildItemSearchType(functionSearchType[i], lowercasePaths)] + : this.buildItemSearchTypeAll(functionSearchType[i], lowercasePaths)); + } + return { + inputs, output, where_clause, + }; + }; + }; + + const searchIndex = []; + let currentIndex = 0; + let id = 0; - if (filterCrates !== null) { - extra += "&filter-crate=" + encodeURIComponent(filterCrates); + // Function type fingerprints are 128-bit bloom filters that are used to + // estimate the distance between function and query. + // This loop counts the number of items to allocate a fingerprint for. + for (const crate of rawSearchIndex.values()) { + // Each item gets an entry in the fingerprint array, and the crate + // does, too + id += crate.t.length + 1; } - return getNakedUrl() + extra + window.location.hash; - } + this.functionTypeFingerprint = new Uint32Array((id + 1) * 4); + // This loop actually generates the search item indexes, including + // normalized names, type signature objects and fingerprints, and aliases. + id = 0; - /** - * Return the filtering crate or `null` if there is none. - * - * @return {string|null} - */ - function getFilterCrates() { - const elem = document.getElementById("crate-search"); + for (const [crate, crateCorpus] of rawSearchIndex) { + // a string representing the lengths of each description shard + // a string representing the list of function types + const itemDescShardDecoder = new VlqHexDecoder(crateCorpus.D, noop => noop); + let descShard = { + crate, + shard: 0, + start: 0, + len: itemDescShardDecoder.next(), + promise: null, + resolve: null, + }; + const descShardList = [descShard]; - if (elem && - elem.value !== "all crates" && - rawSearchIndex.has(elem.value) - ) { - return elem.value; + // Deprecated items and items with no description + this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); + this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); + let descIndex = 0; + + // This object should have exactly the same set of fields as the "row" + // object defined below. Your JavaScript runtime will thank you. + // https://mathiasbynens.be/notes/shapes-ics + const crateRow = { + crate, + ty: 3, // == ExternCrate + name: crate, + path: "", + descShard, + descIndex, + exactPath: "", + desc: crateCorpus.doc, + parent: undefined, + type: null, + id, + word: crate, + normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""), + bitIndex: 0, + implDisambiguator: null, + }; + id += 1; + searchIndex.push(crateRow); + currentIndex += 1; + if (!this.searchIndexEmptyDesc.get(crate).contains(0)) { + descIndex += 1; + } + + // a String of one character item type codes + const itemTypes = crateCorpus.t; + // an array of (String) item names + const itemNames = crateCorpus.n; + // an array of [(Number) item index, + // (String) full path] + // an item whose index is not present will fall back to the previous present path + // i.e. if indices 4 and 11 are present, but 5-10 and 12-13 are not present, + // 5-10 will fall back to the path for 4 and 12-13 will fall back to the path for 11 + const itemPaths = new Map(crateCorpus.q); + // An array of [(Number) item index, (Number) path index] + // Used to de-duplicate inlined and re-exported stuff + const itemReexports = new Map(crateCorpus.r); + // an array of (Number) the parent path index + 1 to `paths`, or 0 if none + const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); + // a map Number, string for impl disambiguators + const implDisambiguator = new Map(crateCorpus.b); + // an array of [(Number) item type, + // (String) name] + const paths = crateCorpus.p; + // an array of [(String) alias name + // [Number] index to items] + const aliases = crateCorpus.a; + + // an array of [{name: String, ty: Number}] + const lowercasePaths = []; + + // a string representing the list of function types + const itemFunctionDecoder = new VlqHexDecoder( + crateCorpus.f, + buildFunctionSearchTypeCallback(lowercasePaths), + ); + + // convert `rawPaths` entries into object form + // generate normalizedPaths for function search mode + let len = paths.length; + let lastPath = itemPaths.get(0); + for (let i = 0; i < len; ++i) { + const elem = paths[i]; + const ty = elem[0]; + const name = elem[1]; + let path = null; + if (elem.length > 2) { + path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; + lastPath = path; + } + const exactPath = elem.length > 3 ? itemPaths.get(elem[3]) : path; + + lowercasePaths.push({ ty, name: name.toLowerCase(), path, exactPath }); + paths[i] = { ty, name, path, exactPath }; + } + + // convert `item*` into an object form, and construct word indices. + // + // before any analysis is performed lets gather the search terms to + // search against apart from the rest of the data. This is a quick + // operation that is cached for the life of the page state so that + // all other search operations have access to this cached data for + // faster analysis operations + lastPath = ""; + len = itemTypes.length; + let lastName = ""; + let lastWord = ""; + for (let i = 0; i < len; ++i) { + const bitIndex = i + 1; + if (descIndex >= descShard.len && + !this.searchIndexEmptyDesc.get(crate).contains(bitIndex)) { + descShard = { + crate, + shard: descShard.shard + 1, + start: descShard.start + descShard.len, + len: itemDescShardDecoder.next(), + promise: null, + resolve: null, + }; + descIndex = 0; + descShardList.push(descShard); + } + const name = itemNames[i] === "" ? lastName : itemNames[i]; + const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); + const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; + const type = itemFunctionDecoder.next(); + if (type !== null) { + if (type) { + const fp = this.functionTypeFingerprint.subarray(id * 4, (id + 1) * 4); + const fps = new Set(); + for (const t of type.inputs) { + this.buildFunctionTypeFingerprint(t, fp, fps); + } + for (const t of type.output) { + this.buildFunctionTypeFingerprint(t, fp, fps); + } + for (const w of type.where_clause) { + for (const t of w) { + this.buildFunctionTypeFingerprint(t, fp, fps); + } + } + } + } + // This object should have exactly the same set of fields as the "crateRow" + // object defined above. + const itemParentIdx = itemParentIdxDecoder.next(); + const row = { + crate, + ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" + name, + path, + descShard, + descIndex, + exactPath: itemReexports.has(i) ? + itemPaths.get(itemReexports.get(i)) : path, + parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined, + type, + id, + word, + normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""), + bitIndex, + implDisambiguator: implDisambiguator.has(i) ? + implDisambiguator.get(i) : null, + }; + id += 1; + searchIndex.push(row); + lastPath = row.path; + if (!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)) { + descIndex += 1; + } + lastName = name; + lastWord = word; + } + + if (aliases) { + const currentCrateAliases = new Map(); + this.ALIASES.set(crate, currentCrateAliases); + for (const alias_name in aliases) { + if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) { + continue; + } + + let currentNameAliases; + if (currentCrateAliases.has(alias_name)) { + currentNameAliases = currentCrateAliases.get(alias_name); + } else { + currentNameAliases = []; + currentCrateAliases.set(alias_name, currentNameAliases); + } + for (const local_alias of aliases[alias_name]) { + currentNameAliases.push(local_alias + currentIndex); + } + } + } + currentIndex += itemTypes.length; + this.searchState.descShards.set(crate, descShardList); } - return null; + // Drop the (rather large) hash table used for reusing function items + this.TYPES_POOL = new Map(); + return searchIndex; } /** @@ -1249,7 +1748,15 @@ function initSearch(rawSearchIndex) { * * @return {ParsedQuery} - The parsed query */ - function parseQuery(userQuery) { + static parseQuery(userQuery) { + function itemTypeFromName(typename) { + const index = itemTypes.findIndex(i => i === typename); + if (index < 0) { + throw ["Unknown type filter ", typename]; + } + return index; + } + function convertTypeFilterOnElem(elem) { if (elem.typeFilter !== null) { let typeFilter = elem.typeFilter; @@ -1269,6 +1776,130 @@ function initSearch(rawSearchIndex) { } } } + + /** + * Takes the user search input and returns an empty `ParsedQuery`. + * + * @param {string} userQuery + * + * @return {ParsedQuery} + */ + function newParsedQuery(userQuery) { + return { + original: userQuery, + userQuery: userQuery.toLowerCase(), + elems: [], + returned: [], + // Total number of "top" elements (does not include generics). + foundElems: 0, + // Total number of elements (includes generics). + totalElems: 0, + literalSearch: false, + error: null, + correction: null, + proposeCorrectionFrom: null, + proposeCorrectionTo: null, + // bloom filter build from type ids + typeFingerprint: new Uint32Array(4), + }; + } + + /** + * Parses the provided `query` input to fill `parserState`. If it encounters an error while + * parsing `query`, it'll throw an error. + * + * @param {ParsedQuery} query + * @param {ParserState} parserState + */ + function parseInput(query, parserState) { + let foundStopChar = true; + + while (parserState.pos < parserState.length) { + const c = parserState.userQuery[parserState.pos]; + if (isEndCharacter(c)) { + foundStopChar = true; + if (isSeparatorCharacter(c)) { + parserState.pos += 1; + continue; + } else if (c === "-" || c === ">") { + if (isReturnArrow(parserState)) { + break; + } + throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; + } else if (parserState.pos > 0) { + throw ["Unexpected ", c, " after ", + parserState.userQuery[parserState.pos - 1]]; + } + throw ["Unexpected ", c]; + } else if (c === " ") { + skipWhitespace(parserState); + continue; + } + if (!foundStopChar) { + let extra = ""; + if (isLastElemGeneric(query.elems, parserState)) { + extra = [" after ", ">"]; + } else if (prevIs(parserState, "\"")) { + throw ["Cannot have more than one element if you use quotes"]; + } + if (parserState.typeFilter !== null) { + throw [ + "Expected ", + ",", + " or ", + "->", + ...extra, + ", found ", + c, + ]; + } + throw [ + "Expected ", + ",", + ", ", + ":", + " or ", + "->", + ...extra, + ", found ", + c, + ]; + } + const before = query.elems.length; + getFilteredNextElem(query, parserState, query.elems, false); + if (query.elems.length === before) { + // Nothing was added, weird... Let's increase the position to not remain stuck. + parserState.pos += 1; + } + foundStopChar = false; + } + if (parserState.typeFilter !== null) { + throw [ + "Unexpected ", + ":", + " (expected path after type filter ", + parserState.typeFilter + ":", + ")", + ]; + } + while (parserState.pos < parserState.length) { + if (isReturnArrow(parserState)) { + parserState.pos += 2; + skipWhitespace(parserState); + // Get returned elements. + getItemsBefore(query, parserState, query.returned, ""); + // Nothing can come afterward! + if (query.returned.length === 0) { + throw ["Expected at least one item after ", "->"]; + } + break; + } else { + parserState.pos += 1; + } + } + } + + userQuery = userQuery.trim().replace(/\r|\n|\t/g, " "); const parserState = { length: userQuery.length, @@ -1306,25 +1937,6 @@ function initSearch(rawSearchIndex) { } /** - * Creates the query results. - * - * @param {Array<Result>} results_in_args - * @param {Array<Result>} results_returned - * @param {Array<Result>} results_others - * @param {ParsedQuery} parsedQuery - * - * @return {ResultsTable} - */ - function createQueryResults(results_in_args, results_returned, results_others, parsedQuery) { - return { - "in_args": results_in_args, - "returned": results_returned, - "others": results_others, - "query": parsedQuery, - }; - } - - /** * Executes the parsed query and builds a {ResultsTable}. * * @param {ParsedQuery} parsedQuery - The parsed user query @@ -1333,24 +1945,116 @@ function initSearch(rawSearchIndex) { * * @return {ResultsTable} */ - async function execQuery(parsedQuery, filterCrates, currentCrate) { + async execQuery(parsedQuery, filterCrates, currentCrate) { const results_others = new Map(), results_in_args = new Map(), results_returned = new Map(); /** + * Creates the query results. + * + * @param {Array<Result>} results_in_args + * @param {Array<Result>} results_returned + * @param {Array<Result>} results_others + * @param {ParsedQuery} parsedQuery + * + * @return {ResultsTable} + */ + function createQueryResults( + results_in_args, + results_returned, + results_others, + parsedQuery) { + return { + "in_args": results_in_args, + "returned": results_returned, + "others": results_others, + "query": parsedQuery, + }; + } + + const buildHrefAndPath = item => { + let displayPath; + let href; + const type = itemTypes[item.ty]; + const name = item.name; + let path = item.path; + let exactPath = item.exactPath; + + if (type === "mod") { + displayPath = path + "::"; + href = this.rootPath + path.replace(/::/g, "/") + "/" + + name + "/index.html"; + } else if (type === "import") { + displayPath = item.path + "::"; + href = this.rootPath + item.path.replace(/::/g, "/") + + "/index.html#reexport." + name; + } else if (type === "primitive" || type === "keyword") { + displayPath = ""; + href = this.rootPath + path.replace(/::/g, "/") + + "/" + type + "." + name + ".html"; + } else if (type === "externcrate") { + displayPath = ""; + href = this.rootPath + name + "/index.html"; + } else if (item.parent !== undefined) { + const myparent = item.parent; + let anchor = type + "." + name; + const parentType = itemTypes[myparent.ty]; + let pageType = parentType; + let pageName = myparent.name; + exactPath = `${myparent.exactPath}::${myparent.name}`; + + if (parentType === "primitive") { + displayPath = myparent.name + "::"; + } else if (type === "structfield" && parentType === "variant") { + // Structfields belonging to variants are special: the + // final path element is the enum name. + const enumNameIdx = item.path.lastIndexOf("::"); + const enumName = item.path.substr(enumNameIdx + 2); + path = item.path.substr(0, enumNameIdx); + displayPath = path + "::" + enumName + "::" + myparent.name + "::"; + anchor = "variant." + myparent.name + ".field." + name; + pageType = "enum"; + pageName = enumName; + } else { + displayPath = path + "::" + myparent.name + "::"; + } + if (item.implDisambiguator !== null) { + anchor = item.implDisambiguator + "/" + anchor; + } + href = this.rootPath + path.replace(/::/g, "/") + + "/" + pageType + + "." + pageName + + ".html#" + anchor; + } else { + displayPath = item.path + "::"; + href = this.rootPath + item.path.replace(/::/g, "/") + + "/" + type + "." + name + ".html"; + } + return [displayPath, href, `${exactPath}::${name}`]; + }; + + function pathSplitter(path) { + const tmp = "<span>" + path.replace(/::/g, "::</span><span>"); + if (tmp.endsWith("<span>")) { + return tmp.slice(0, tmp.length - 6); + } + return tmp; + } + + /** * Add extra data to result objects, and filter items that have been * marked for removal. * * @param {[ResultObject]} results * @returns {[ResultObject]} */ - function transformResults(results) { + const transformResults = results => { const duplicates = new Set(); const out = []; for (const result of results) { if (result.id !== -1) { - const obj = searchIndex[result.id]; + const obj = this.searchIndex[result.id]; obj.dist = result.dist; const res = buildHrefAndPath(obj); obj.displayPath = pathSplitter(res[0]); @@ -1380,7 +2084,7 @@ function initSearch(rawSearchIndex) { } } return out; - } + }; /** * This function takes a result map, and sorts it by various criteria, including edit @@ -1391,13 +2095,13 @@ function initSearch(rawSearchIndex) { * @param {string} preferredCrate * @returns {Promise<[ResultObject]>} */ - async function sortResults(results, isType, preferredCrate) { + const sortResults = async(results, isType, preferredCrate) => { const userQuery = parsedQuery.userQuery; const casedUserQuery = parsedQuery.original; const result_list = []; for (const result of results.values()) { - result.item = searchIndex[result.id]; - result.word = searchIndex[result.id].word; + result.item = this.searchIndex[result.id]; + result.word = this.searchIndex[result.id].word; result_list.push(result); } @@ -1449,8 +2153,8 @@ function initSearch(rawSearchIndex) { } // sort deprecated items later - a = searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex); - b = searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex); + a = this.searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex); + b = this.searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex); if (a !== b) { return a - b; } @@ -1477,8 +2181,8 @@ function initSearch(rawSearchIndex) { } // sort by description (no description goes later) - a = searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex); - b = searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex); + a = this.searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex); + b = this.searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex); if (a !== b) { return a - b; } @@ -1502,7 +2206,7 @@ function initSearch(rawSearchIndex) { }); return transformResults(result_list); - } + }; /** * This function checks if a list of search query `queryElems` can all be found in the @@ -1601,7 +2305,7 @@ function initSearch(rawSearchIndex) { return true; } } else if (unifyFunctionTypes( - [...fnType.generics, ...Array.from(fnType.bindings.values()).flat() ], + [...fnType.generics, ...Array.from(fnType.bindings.values()).flat()], queryElems, whereClause, mgens ? new Map(mgens) : null, @@ -1766,7 +2470,7 @@ function initSearch(rawSearchIndex) { * @param {Map<number,number>|null} mgensIn - Map functions generics to query generics. * @returns {boolean} */ - function unifyFunctionTypeIsMatchCandidate(fnType, queryElem, mgensIn) { + const unifyFunctionTypeIsMatchCandidate = (fnType, queryElem, mgensIn) => { // type filters look like `trait:Read` or `enum:Result` if (!typePassesFilter(queryElem.typeFilter, fnType.ty)) { return false; @@ -1792,19 +2496,19 @@ function initSearch(rawSearchIndex) { } return true; } else { - if (queryElem.id === typeNameIdOfArrayOrSlice && - (fnType.id === typeNameIdOfSlice || fnType.id === typeNameIdOfArray) + if (queryElem.id === this.typeNameIdOfArrayOrSlice && + (fnType.id === this.typeNameIdOfSlice || fnType.id === this.typeNameIdOfArray) ) { // [] matches primitive:array or primitive:slice // if it matches, then we're fine, and this is an appropriate match candidate - } else if (queryElem.id === typeNameIdOfTupleOrUnit && - (fnType.id === typeNameIdOfTuple || fnType.id === typeNameIdOfUnit) + } else if (queryElem.id === this.typeNameIdOfTupleOrUnit && + (fnType.id === this.typeNameIdOfTuple || fnType.id === this.typeNameIdOfUnit) ) { // () matches primitive:tuple or primitive:unit // if it matches, then we're fine, and this is an appropriate match candidate - } else if (queryElem.id === typeNameIdOfHof && - (fnType.id === typeNameIdOfFn || fnType.id === typeNameIdOfFnMut || - fnType.id === typeNameIdOfFnOnce) + } else if (queryElem.id === this.typeNameIdOfHof && + (fnType.id === this.typeNameIdOfFn || fnType.id === this.typeNameIdOfFnMut || + fnType.id === this.typeNameIdOfFnOnce) ) { // -> matches fn, fnonce, and fnmut // if it matches, then we're fine, and this is an appropriate match candidate @@ -1849,7 +2553,7 @@ function initSearch(rawSearchIndex) { } return true; } - } + }; /** * This function checks the associated type bindings. Any that aren't matched get converted * to generics, and this function returns an array of the function's generics with these @@ -1988,17 +2692,17 @@ function initSearch(rawSearchIndex) { } /** - * This function checks if the object (`row`) matches the given type (`elem`) and its - * generics (if any). - * - * @param {Array<FunctionType>} list - * @param {QueryElement} elem - The element from the parsed query. - * @param {[FunctionType]} whereClause - Trait bounds for generic items. - * @param {Map<number,number>|null} mgens - Map functions generics to query generics. - * @param {number} unboxingDepth - * - * @return {boolean} - Returns true if found, false otherwise. - */ + * This function checks if the object (`row`) matches the given type (`elem`) and its + * generics (if any). + * + * @param {Array<FunctionType>} list + * @param {QueryElement} elem - The element from the parsed query. + * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map<number,number>|null} mgens - Map functions generics to query generics. + * @param {number} unboxingDepth + * + * @return {boolean} - Returns true if found, false otherwise. + */ function checkIfInList(list, elem, whereClause, mgens, unboxingDepth) { for (const entry of list) { if (checkType(entry, elem, whereClause, mgens, unboxingDepth)) { @@ -2009,17 +2713,17 @@ function initSearch(rawSearchIndex) { } /** - * This function checks if the object (`row`) matches the given type (`elem`) and its - * generics (if any). - * - * @param {Row} row - * @param {QueryElement} elem - The element from the parsed query. - * @param {[FunctionType]} whereClause - Trait bounds for generic items. - * @param {Map<number,number>|null} mgens - Map functions generics to query generics. - * - * @return {boolean} - Returns true if the type matches, false otherwise. - */ - function checkType(row, elem, whereClause, mgens, unboxingDepth) { + * This function checks if the object (`row`) matches the given type (`elem`) and its + * generics (if any). + * + * @param {Row} row + * @param {QueryElement} elem - The element from the parsed query. + * @param {[FunctionType]} whereClause - Trait bounds for generic items. + * @param {Map<number,number>|null} mgens - Map functions generics to query generics. + * + * @return {boolean} - Returns true if the type matches, false otherwise. + */ + const checkType = (row, elem, whereClause, mgens, unboxingDepth) => { if (unboxingDepth >= UNBOXING_LIMIT) { return false; } @@ -2036,8 +2740,9 @@ function initSearch(rawSearchIndex) { if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 && typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 && // special case - elem.id !== typeNameIdOfArrayOrSlice && elem.id !== typeNameIdOfTupleOrUnit - && elem.id !== typeNameIdOfHof + elem.id !== this.typeNameIdOfArrayOrSlice + && elem.id !== this.typeNameIdOfTupleOrUnit + && elem.id !== this.typeNameIdOfHof ) { return row.id === elem.id || checkIfInList( row.generics, @@ -2049,7 +2754,7 @@ function initSearch(rawSearchIndex) { } } return unifyFunctionTypes([row], [elem], whereClause, mgens, null, unboxingDepth); - } + }; /** * Compute an "edit distance" that ignores missing path elements. @@ -2133,26 +2838,27 @@ function initSearch(rawSearchIndex) { }; } - async function handleAliases(ret, query, filterCrates, currentCrate) { + const handleAliases = async(ret, query, filterCrates, currentCrate) => { const lowerQuery = query.toLowerCase(); // We separate aliases and crate aliases because we want to have current crate // aliases to be before the others in the displayed results. const aliases = []; const crateAliases = []; if (filterCrates !== null) { - if (ALIASES.has(filterCrates) && ALIASES.get(filterCrates).has(lowerQuery)) { - const query_aliases = ALIASES.get(filterCrates).get(lowerQuery); + if (this.ALIASES.has(filterCrates) + && this.ALIASES.get(filterCrates).has(lowerQuery)) { + const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery); for (const alias of query_aliases) { - aliases.push(createAliasFromItem(searchIndex[alias])); + aliases.push(createAliasFromItem(this.searchIndex[alias])); } } } else { - for (const [crate, crateAliasesIndex] of ALIASES) { + for (const [crate, crateAliasesIndex] of this.ALIASES) { if (crateAliasesIndex.has(lowerQuery)) { const pushTo = crate === currentCrate ? crateAliases : aliases; const query_aliases = crateAliasesIndex.get(lowerQuery); for (const alias of query_aliases) { - pushTo.push(createAliasFromItem(searchIndex[alias])); + pushTo.push(createAliasFromItem(this.searchIndex[alias])); } } } @@ -2170,8 +2876,8 @@ function initSearch(rawSearchIndex) { aliases.sort(sortFunc); const fetchDesc = alias => { - return searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ? - "" : searchState.loadDesc(alias); + return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ? + "" : this.searchState.loadDesc(alias); }; const [crateDescs, descs] = await Promise.all([ Promise.all(crateAliases.map(fetchDesc)), @@ -2199,7 +2905,7 @@ function initSearch(rawSearchIndex) { alias.desc = crateDescs[i]; }); crateAliases.forEach(pushFunc); - } + }; /** * This function adds the given result into the provided `results` map if it matches the @@ -2382,7 +3088,41 @@ function initSearch(rawSearchIndex) { addIntoResults(results, row.id, pos, 0, tfpDist, 0, Number.MAX_VALUE); } - function innerRunQuery() { + /** + * Compare the query fingerprint with the function fingerprint. + * + * @param {{number}} fullId - The function + * @param {{Uint32Array}} queryFingerprint - The query + * @returns {number|null} - Null if non-match, number if distance + * This function might return 0! + */ + const compareTypeFingerprints = (fullId, queryFingerprint) => { + const fh0 = this.functionTypeFingerprint[fullId * 4]; + const fh1 = this.functionTypeFingerprint[(fullId * 4) + 1]; + const fh2 = this.functionTypeFingerprint[(fullId * 4) + 2]; + const [qh0, qh1, qh2] = queryFingerprint; + // Approximate set intersection with bloom filters. + // This can be larger than reality, not smaller, because hashes have + // the property that if they've got the same value, they hash to the + // same thing. False positives exist, but not false negatives. + const [in0, in1, in2] = [fh0 & qh0, fh1 & qh1, fh2 & qh2]; + // Approximate the set of items in the query but not the function. + // This might be smaller than reality, but cannot be bigger. + // + // | in_ | qh_ | XOR | Meaning | + // | --- | --- | --- | ------------------------------------------------ | + // | 0 | 0 | 0 | Not present | + // | 1 | 0 | 1 | IMPOSSIBLE because `in_` is `fh_ & qh_` | + // | 1 | 1 | 0 | If one or both is false positive, false negative | + // | 0 | 1 | 1 | Since in_ has no false negatives, must be real | + if ((in0 ^ qh0) || (in1 ^ qh1) || (in2 ^ qh2)) { + return null; + } + return this.functionTypeFingerprint[(fullId * 4) + 3]; + }; + + + const innerRunQuery = () => { const queryLen = parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) + parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0); @@ -2406,16 +3146,16 @@ function initSearch(rawSearchIndex) { * @param {QueryElement} elem * @param {boolean} isAssocType */ - function convertNameToId(elem, isAssocType) { + const convertNameToId = (elem, isAssocType) => { const loweredName = elem.pathLast.toLowerCase(); - if (typeNameIdMap.has(loweredName) && - (isAssocType || !typeNameIdMap.get(loweredName).assocOnly)) { - elem.id = typeNameIdMap.get(loweredName).id; + if (this.typeNameIdMap.has(loweredName) && + (isAssocType || !this.typeNameIdMap.get(loweredName).assocOnly)) { + elem.id = this.typeNameIdMap.get(loweredName).id; } else if (!parsedQuery.literalSearch) { let match = null; let matchDist = maxEditDistance + 1; let matchName = ""; - for (const [name, {id, assocOnly}] of typeNameIdMap) { + for (const [name, { id, assocOnly }] of this.typeNameIdMap) { const dist = Math.min( editDistance(name, loweredName, maxEditDistance), editDistance(name, elem.normalizedPathLast, maxEditDistance), @@ -2436,7 +3176,7 @@ function initSearch(rawSearchIndex) { elem.id = match; } if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1 - && elem.generics.length === 0 && elem.bindings.size === 0) + && elem.generics.length === 0 && elem.bindings.size === 0) || elem.typeFilter === TY_GENERIC) { if (genericSymbols.has(elem.name)) { elem.id = genericSymbols.get(elem.name); @@ -2451,7 +3191,7 @@ function initSearch(rawSearchIndex) { const maxPartDistance = Math.floor(elem.name.length / 3); let matchDist = maxPartDistance + 1; let matchName = ""; - for (const name of typeNameIdMap.keys()) { + for (const name of this.typeNameIdMap.keys()) { const dist = editDistance(name, elem.name, maxPartDistance); if (dist <= matchDist && dist <= maxPartDistance) { if (dist === matchDist && matchName > name) { @@ -2482,7 +3222,7 @@ function initSearch(rawSearchIndex) { elem.bindings = new Map(Array.from(elem.bindings.entries()) .map(entry => { const [name, constraints] = entry; - if (!typeNameIdMap.has(name)) { + if (!this.typeNameIdMap.has(name)) { parsedQuery.error = [ "Type parameter ", name, @@ -2494,29 +3234,30 @@ function initSearch(rawSearchIndex) { convertNameToId(elem2); } - return [typeNameIdMap.get(name).id, constraints]; + return [this.typeNameIdMap.get(name).id, constraints]; }), ); - } + }; const fps = new Set(); for (const elem of parsedQuery.elems) { convertNameToId(elem); - buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); + this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); } for (const elem of parsedQuery.returned) { convertNameToId(elem); - buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); + this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); } if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) { if (parsedQuery.elems.length === 1) { const elem = parsedQuery.elems[0]; - for (let i = 0, nSearchIndex = searchIndex.length; i < nSearchIndex; ++i) { + const length = this.searchIndex.length; + for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) { // It means we want to check for this element everywhere (in names, args and // returned). handleSingleArg( - searchIndex[i], + this.searchIndex[i], i, elem, results_others, @@ -2543,11 +3284,11 @@ function initSearch(rawSearchIndex) { }; parsedQuery.elems.sort(sortQ); parsedQuery.returned.sort(sortQ); - for (let i = 0, nSearchIndex = searchIndex.length; i < nSearchIndex; ++i) { - handleArgs(searchIndex[i], i, results_others); + for (let i = 0, nSearchIndex = this.searchIndex.length; i < nSearchIndex; ++i) { + handleArgs(this.searchIndex[i], i, results_others); } } - } + }; if (parsedQuery.error === null) { innerRunQuery(); @@ -2567,9 +3308,9 @@ function initSearch(rawSearchIndex) { filterCrates, currentCrate); await Promise.all([ret.others, ret.returned, ret.in_args].map(async list => { const descs = await Promise.all(list.map(result => { - return searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ? + return this.searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ? "" : - searchState.loadDesc(result); + this.searchState.loadDesc(result); })); for (const [i, result] of list.entries()) { result.desc = descs[i]; @@ -2581,1310 +3322,610 @@ function initSearch(rawSearchIndex) { } return ret; } +} - function nextTab(direction) { - const next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length; - searchState.focusedByTab[searchState.currentTab] = document.activeElement; - printTab(next); - focusSearchResult(); - } - - // Focus the first search result on the active tab, or the result that - // was focused last time this tab was active. - function focusSearchResult() { - const target = searchState.focusedByTab[searchState.currentTab] || - document.querySelectorAll(".search-results.active a").item(0) || - document.querySelectorAll("#search-tabs button").item(searchState.currentTab); - searchState.focusedByTab[searchState.currentTab] = null; - if (target) { - target.focus(); - } - } - - function buildHrefAndPath(item) { - let displayPath; - let href; - const type = itemTypes[item.ty]; - const name = item.name; - let path = item.path; - let exactPath = item.exactPath; - - if (type === "mod") { - displayPath = path + "::"; - href = ROOT_PATH + path.replace(/::/g, "/") + "/" + - name + "/index.html"; - } else if (type === "import") { - displayPath = item.path + "::"; - href = ROOT_PATH + item.path.replace(/::/g, "/") + "/index.html#reexport." + name; - } else if (type === "primitive" || type === "keyword") { - displayPath = ""; - href = ROOT_PATH + path.replace(/::/g, "/") + - "/" + type + "." + name + ".html"; - } else if (type === "externcrate") { - displayPath = ""; - href = ROOT_PATH + name + "/index.html"; - } else if (item.parent !== undefined) { - const myparent = item.parent; - let anchor = type + "." + name; - const parentType = itemTypes[myparent.ty]; - let pageType = parentType; - let pageName = myparent.name; - exactPath = `${myparent.exactPath}::${myparent.name}`; - - if (parentType === "primitive") { - displayPath = myparent.name + "::"; - } else if (type === "structfield" && parentType === "variant") { - // Structfields belonging to variants are special: the - // final path element is the enum name. - const enumNameIdx = item.path.lastIndexOf("::"); - const enumName = item.path.substr(enumNameIdx + 2); - path = item.path.substr(0, enumNameIdx); - displayPath = path + "::" + enumName + "::" + myparent.name + "::"; - anchor = "variant." + myparent.name + ".field." + name; - pageType = "enum"; - pageName = enumName; - } else { - displayPath = path + "::" + myparent.name + "::"; - } - if (item.implDisambiguator !== null) { - anchor = item.implDisambiguator + "/" + anchor; - } - href = ROOT_PATH + path.replace(/::/g, "/") + - "/" + pageType + - "." + pageName + - ".html#" + anchor; - } else { - displayPath = item.path + "::"; - href = ROOT_PATH + item.path.replace(/::/g, "/") + - "/" + type + "." + name + ".html"; - } - return [displayPath, href, `${exactPath}::${name}`]; - } - - function pathSplitter(path) { - const tmp = "<span>" + path.replace(/::/g, "::</span><span>"); - if (tmp.endsWith("<span>")) { - return tmp.slice(0, tmp.length - 6); - } - return tmp; - } - - /** - * Render a set of search results for a single tab. - * @param {Array<?>} array - The search results for this tab - * @param {ParsedQuery} query - * @param {boolean} display - True if this is the active tab - */ - async function addTab(array, query, display) { - const extraClass = display ? " active" : ""; - - const output = document.createElement("div"); - if (array.length > 0) { - output.className = "search-results " + extraClass; - - for (const item of array) { - const name = item.name; - const type = itemTypes[item.ty]; - const longType = longItemTypes[item.ty]; - const typeName = longType.length !== 0 ? `${longType}` : "?"; - - const link = document.createElement("a"); - link.className = "result-" + type; - link.href = item.href; - - const resultName = document.createElement("div"); - resultName.className = "result-name"; - - resultName.insertAdjacentHTML( - "beforeend", - `<span class="typename">${typeName}</span>`); - link.appendChild(resultName); - - let alias = " "; - if (item.is_alias) { - alias = ` <div class="alias">\ -<b>${item.alias}</b><i class="grey"> - see </i>\ -</div>`; - } - resultName.insertAdjacentHTML( - "beforeend", - `<div class="path">${alias}\ -${item.displayPath}<span class="${type}">${name}</span>\ -</div>`); - - const description = document.createElement("div"); - description.className = "desc"; - description.insertAdjacentHTML("beforeend", item.desc); - - link.appendChild(description); - output.appendChild(link); - } - } else if (query.error === null) { - output.className = "search-failed" + extraClass; - output.innerHTML = "No results :(<br/>" + - "Try on <a href=\"https://duckduckgo.com/?q=" + - encodeURIComponent("rust " + query.userQuery) + - "\">DuckDuckGo</a>?<br/><br/>" + - "Or try looking in one of these:<ul><li>The <a " + - "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " + - " for technical details about the language.</li><li><a " + - "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " + - "Example</a> for expository code examples.</a></li><li>The <a " + - "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " + - "introductions to language features and the language itself.</li><li><a " + - "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" + - " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>"; - } - return [output, array.length]; - } - - function makeTabHeader(tabNb, text, nbElems) { - // https://blog.horizon-eda.org/misc/2020/02/19/ui.html - // - // CSS runs with `font-variant-numeric: tabular-nums` to ensure all - // digits are the same width. \u{2007} is a Unicode space character - // that is defined to be the same width as a digit. - const fmtNbElems = - nbElems < 10 ? `\u{2007}(${nbElems})\u{2007}\u{2007}` : - nbElems < 100 ? `\u{2007}(${nbElems})\u{2007}` : - `\u{2007}(${nbElems})`; - if (searchState.currentTab === tabNb) { - return "<button class=\"selected\">" + text + - "<span class=\"count\">" + fmtNbElems + "</span></button>"; - } - return "<button>" + text + "<span class=\"count\">" + fmtNbElems + "</span></button>"; - } - - /** - * @param {ResultsTable} results - * @param {boolean} go_to_first - * @param {string} filterCrates - */ - async function showResults(results, go_to_first, filterCrates) { - const search = searchState.outputElement(); - if (go_to_first || (results.others.length === 1 - && getSettingValue("go-to-only-result") === "true") - ) { - // Needed to force re-execution of JS when coming back to a page. Let's take this - // scenario as example: - // - // 1. You have the "Directly go to item in search if there is only one result" option - // enabled. - // 2. You make a search which results only one result, leading you automatically to - // this result. - // 3. You go back to previous page. - // - // Now, without the call below, the JS will not be re-executed and the previous state - // will be used, starting search again since the search input is not empty, leading you - // back to the previous page again. - window.onunload = () => {}; - searchState.removeQueryParameters(); - const elem = document.createElement("a"); - elem.href = results.others[0].href; - removeClass(elem, "active"); - // For firefox, we need the element to be in the DOM so it can be clicked. - document.body.appendChild(elem); - elem.click(); - return; - } - if (results.query === undefined) { - results.query = parseQuery(searchState.input.value); - } - - currentResults = results.query.userQuery; +// ==================== Core search logic end ==================== - const [ret_others, ret_in_args, ret_returned] = await Promise.all([ - addTab(results.others, results.query, true), - addTab(results.in_args, results.query, false), - addTab(results.returned, results.query, false), - ]); +let rawSearchIndex; +let docSearch; +const longItemTypes = [ + "keyword", + "primitive type", + "module", + "extern crate", + "re-export", + "struct", + "enum", + "function", + "type alias", + "static", + "trait", + "", + "trait method", + "method", + "struct field", + "enum variant", + "macro", + "assoc type", + "constant", + "assoc const", + "union", + "foreign type", + "existential type", + "attribute macro", + "derive macro", + "trait alias", +]; +let currentResults; - // Navigate to the relevant tab if the current tab is empty, like in case users search - // for "-> String". If they had selected another tab previously, they have to click on - // it again. - let currentTab = searchState.currentTab; - if ((currentTab === 0 && ret_others[1] === 0) || - (currentTab === 1 && ret_in_args[1] === 0) || - (currentTab === 2 && ret_returned[1] === 0)) { - if (ret_others[1] !== 0) { - currentTab = 0; - } else if (ret_in_args[1] !== 0) { - currentTab = 1; - } else if (ret_returned[1] !== 0) { - currentTab = 2; - } - } - - let crates = ""; - if (rawSearchIndex.size > 1) { - crates = " in <div id=\"crate-search-div\"><select id=\"crate-search\">" + - "<option value=\"all crates\">all crates</option>"; - for (const c of rawSearchIndex.keys()) { - crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`; - } - crates += "</select></div>"; - } - - let output = `<h1 class="search-results-title">Results${crates}</h1>`; - if (results.query.error !== null) { - const error = results.query.error; - error.forEach((value, index) => { - value = value.split("<").join("<").split(">").join(">"); - if (index % 2 !== 0) { - error[index] = `<code>${value.replaceAll(" ", " ")}</code>`; - } else { - error[index] = value; - } - }); - output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`; - output += "<div id=\"search-tabs\">" + - makeTabHeader(0, "In Names", ret_others[1]) + - "</div>"; - currentTab = 0; - } else if (results.query.foundElems <= 1 && results.query.returned.length === 0) { - output += "<div id=\"search-tabs\">" + - makeTabHeader(0, "In Names", ret_others[1]) + - makeTabHeader(1, "In Parameters", ret_in_args[1]) + - makeTabHeader(2, "In Return Types", ret_returned[1]) + - "</div>"; +// In the search display, allows to switch between tabs. +function printTab(nb) { + let iter = 0; + let foundCurrentTab = false; + let foundCurrentResultSet = false; + onEachLazy(document.getElementById("search-tabs").childNodes, elem => { + if (nb === iter) { + addClass(elem, "selected"); + foundCurrentTab = true; } else { - const signatureTabTitle = - results.query.elems.length === 0 ? "In Function Return Types" : - results.query.returned.length === 0 ? "In Function Parameters" : - "In Function Signatures"; - output += "<div id=\"search-tabs\">" + - makeTabHeader(0, signatureTabTitle, ret_others[1]) + - "</div>"; - currentTab = 0; + removeClass(elem, "selected"); } - - if (results.query.correction !== null) { - const orig = results.query.returned.length > 0 - ? results.query.returned[0].name - : results.query.elems[0].name; - output += "<h3 class=\"search-corrections\">" + - `Type "${orig}" not found. ` + - "Showing results for closest type name " + - `"${results.query.correction}" instead.</h3>`; - } - if (results.query.proposeCorrectionFrom !== null) { - const orig = results.query.proposeCorrectionFrom; - const targ = results.query.proposeCorrectionTo; - output += "<h3 class=\"search-corrections\">" + - `Type "${orig}" not found and used as generic parameter. ` + - `Consider searching for "${targ}" instead.</h3>`; - } - - const resultsElem = document.createElement("div"); - resultsElem.id = "results"; - resultsElem.appendChild(ret_others[0]); - resultsElem.appendChild(ret_in_args[0]); - resultsElem.appendChild(ret_returned[0]); - - search.innerHTML = output; - const crateSearch = document.getElementById("crate-search"); - if (crateSearch) { - crateSearch.addEventListener("input", updateCrate); - } - search.appendChild(resultsElem); - // Reset focused elements. - searchState.showResults(search); - const elems = document.getElementById("search-tabs").childNodes; - searchState.focusedByTab = []; - let i = 0; - for (const elem of elems) { - const j = i; - elem.onclick = () => printTab(j); - searchState.focusedByTab.push(null); - i += 1; - } - printTab(currentTab); - } - - function updateSearchHistory(url) { - if (!browserSupportsHistoryApi()) { - return; + iter += 1; + }); + const isTypeSearch = (nb > 0 || iter === 1); + iter = 0; + onEachLazy(document.getElementById("results").childNodes, elem => { + if (nb === iter) { + addClass(elem, "active"); + foundCurrentResultSet = true; + } else { + removeClass(elem, "active"); } - const params = searchState.getQueryStringParams(); - if (!history.state && !params.search) { - history.pushState(null, "", url); + iter += 1; + }); + if (foundCurrentTab && foundCurrentResultSet) { + searchState.currentTab = nb; + // Corrections only kick in on type-based searches. + const correctionsElem = document.getElementsByClassName("search-corrections"); + if (isTypeSearch) { + removeClass(correctionsElem[0], "hidden"); } else { - history.replaceState(null, "", url); + addClass(correctionsElem[0], "hidden"); } + } else if (nb !== 0) { + printTab(0); } +} - /** - * Perform a search based on the current state of the search input element - * and display the results. - * @param {boolean} [forced] - */ - async function search(forced) { - const query = parseQuery(searchState.input.value.trim()); - let filterCrates = getFilterCrates(); - - if (!forced && query.userQuery === currentResults) { - if (query.userQuery.length > 0) { - putBackSearch(); - } - return; - } +/** + * Build an URL with search parameters. + * + * @param {string} search - The current search being performed. + * @param {string|null} filterCrates - The current filtering crate (if any). + * + * @return {string} + */ +function buildUrl(search, filterCrates) { + let extra = "?search=" + encodeURIComponent(search); - searchState.setLoadingSearch(); + if (filterCrates !== null) { + extra += "&filter-crate=" + encodeURIComponent(filterCrates); + } + return getNakedUrl() + extra + window.location.hash; +} - const params = searchState.getQueryStringParams(); +/** + * Return the filtering crate or `null` if there is none. + * + * @return {string|null} + */ +function getFilterCrates() { + const elem = document.getElementById("crate-search"); + + if (elem && + elem.value !== "all crates" && + window.searchIndex.has(elem.value) + ) { + return elem.value; + } + return null; +} - // In case we have no information about the saved crate and there is a URL query parameter, - // we override it with the URL query parameter. - if (filterCrates === null && params["filter-crate"] !== undefined) { - filterCrates = params["filter-crate"]; - } +function nextTab(direction) { + const next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length; + searchState.focusedByTab[searchState.currentTab] = document.activeElement; + printTab(next); + focusSearchResult(); +} - // Update document title to maintain a meaningful browser history - searchState.title = "\"" + query.original + "\" Search - Rust"; +// Focus the first search result on the active tab, or the result that +// was focused last time this tab was active. +function focusSearchResult() { + const target = searchState.focusedByTab[searchState.currentTab] || + document.querySelectorAll(".search-results.active a").item(0) || + document.querySelectorAll("#search-tabs button").item(searchState.currentTab); + searchState.focusedByTab[searchState.currentTab] = null; + if (target) { + target.focus(); + } +} - // Because searching is incremental by character, only the most - // recent search query is added to the browser history. - updateSearchHistory(buildUrl(query.original, filterCrates)); +/** + * Render a set of search results for a single tab. + * @param {Array<?>} array - The search results for this tab + * @param {ParsedQuery} query + * @param {boolean} display - True if this is the active tab + */ +async function addTab(array, query, display) { + const extraClass = display ? " active" : ""; + + const output = document.createElement("div"); + if (array.length > 0) { + output.className = "search-results " + extraClass; + + for (const item of array) { + const name = item.name; + const type = itemTypes[item.ty]; + const longType = longItemTypes[item.ty]; + const typeName = longType.length !== 0 ? `${longType}` : "?"; + + const link = document.createElement("a"); + link.className = "result-" + type; + link.href = item.href; + + const resultName = document.createElement("div"); + resultName.className = "result-name"; + + resultName.insertAdjacentHTML( + "beforeend", + `<span class="typename">${typeName}</span>`); + link.appendChild(resultName); + + let alias = " "; + if (item.is_alias) { + alias = ` <div class="alias">\ +<b>${item.alias}</b><i class="grey"> - see </i>\ +</div>`; + } + resultName.insertAdjacentHTML( + "beforeend", + `<div class="path">${alias}\ +${item.displayPath}<span class="${type}">${name}</span>\ +</div>`); - await showResults( - await execQuery(query, filterCrates, window.currentCrate), - params.go_to_first, - filterCrates); + const description = document.createElement("div"); + description.className = "desc"; + description.insertAdjacentHTML("beforeend", item.desc); + + link.appendChild(description); + output.appendChild(link); + } + } else if (query.error === null) { + output.className = "search-failed" + extraClass; + output.innerHTML = "No results :(<br/>" + + "Try on <a href=\"https://duckduckgo.com/?q=" + + encodeURIComponent("rust " + query.userQuery) + + "\">DuckDuckGo</a>?<br/><br/>" + + "Or try looking in one of these:<ul><li>The <a " + + "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " + + " for technical details about the language.</li><li><a " + + "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " + + "Example</a> for expository code examples.</a></li><li>The <a " + + "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " + + "introductions to language features and the language itself.</li><li><a " + + "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" + + " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>"; } + return [output, array.length]; +} - /** - * Convert a list of RawFunctionType / ID to object-based FunctionType. - * - * Crates often have lots of functions in them, and it's common to have a large number of - * functions that operate on a small set of data types, so the search index compresses them - * by encoding function parameter and return types as indexes into an array of names. - * - * Even when a general-purpose compression algorithm is used, this is still a win. I checked. - * https://github.com/rust-lang/rust/pull/98475#issue-1284395985 - * - * The format for individual function types is encoded in - * librustdoc/html/render/mod.rs: impl Serialize for RenderType - * - * @param {null|Array<RawFunctionType>} types - * @param {Array<{name: string, ty: number}>} lowercasePaths - * - * @return {Array<FunctionSearchType>} - */ - function buildItemSearchTypeAll(types, lowercasePaths) { - return types.length > 0 ? - types.map(type => buildItemSearchType(type, lowercasePaths)) : - EMPTY_GENERICS_ARRAY; +function makeTabHeader(tabNb, text, nbElems) { + // https://blog.horizon-eda.org/misc/2020/02/19/ui.html + // + // CSS runs with `font-variant-numeric: tabular-nums` to ensure all + // digits are the same width. \u{2007} is a Unicode space character + // that is defined to be the same width as a digit. + const fmtNbElems = + nbElems < 10 ? `\u{2007}(${nbElems})\u{2007}\u{2007}` : + nbElems < 100 ? `\u{2007}(${nbElems})\u{2007}` : `\u{2007}(${nbElems})`; + if (searchState.currentTab === tabNb) { + return "<button class=\"selected\">" + text + + "<span class=\"count\">" + fmtNbElems + "</span></button>"; } + return "<button>" + text + "<span class=\"count\">" + fmtNbElems + "</span></button>"; +} - /** - * Empty, immutable map used in item search types with no bindings. - * - * @type {Map<number, Array<FunctionType>>} - */ - const EMPTY_BINDINGS_MAP = new Map(); - - /** - * Empty, immutable map used in item search types with no bindings. - * - * @type {Array<FunctionType>} - */ - const EMPTY_GENERICS_ARRAY = []; - - /** - * Object pool for function types with no bindings or generics. - * This is reset after loading the index. - * - * @type {Map<number|null, FunctionType>} - */ - let TYPES_POOL = new Map(); +/** + * @param {ResultsTable} results + * @param {boolean} go_to_first + * @param {string} filterCrates + */ +async function showResults(results, go_to_first, filterCrates) { + const search = searchState.outputElement(); + if (go_to_first || (results.others.length === 1 + && getSettingValue("go-to-only-result") === "true") + ) { + // Needed to force re-execution of JS when coming back to a page. Let's take this + // scenario as example: + // + // 1. You have the "Directly go to item in search if there is only one result" option + // enabled. + // 2. You make a search which results only one result, leading you automatically to + // this result. + // 3. You go back to previous page. + // + // Now, without the call below, the JS will not be re-executed and the previous state + // will be used, starting search again since the search input is not empty, leading you + // back to the previous page again. + window.onunload = () => { }; + searchState.removeQueryParameters(); + const elem = document.createElement("a"); + elem.href = results.others[0].href; + removeClass(elem, "active"); + // For firefox, we need the element to be in the DOM so it can be clicked. + document.body.appendChild(elem); + elem.click(); + return; + } + if (results.query === undefined) { + results.query = DocSearch.parseQuery(searchState.input.value); + } - /** - * Converts a single type. - * - * @param {RawFunctionType} type - */ - function buildItemSearchType(type, lowercasePaths, isAssocType) { - const PATH_INDEX_DATA = 0; - const GENERICS_DATA = 1; - const BINDINGS_DATA = 2; - let pathIndex, generics, bindings; - if (typeof type === "number") { - pathIndex = type; - generics = EMPTY_GENERICS_ARRAY; - bindings = EMPTY_BINDINGS_MAP; - } else { - pathIndex = type[PATH_INDEX_DATA]; - generics = buildItemSearchTypeAll( - type[GENERICS_DATA], - lowercasePaths, - ); - if (type.length > BINDINGS_DATA && type[BINDINGS_DATA].length > 0) { - bindings = new Map(type[BINDINGS_DATA].map(binding => { - const [assocType, constraints] = binding; - // Associated type constructors are represented sloppily in rustdoc's - // type search, to make the engine simpler. - // - // MyType<Output<T>=Result<T>> is equivalent to MyType<Output<Result<T>>=T> - // and both are, essentially - // MyType<Output=(T, Result<T>)>, except the tuple isn't actually there. - // It's more like the value of a type binding is naturally an array, - // which rustdoc calls "constraints". - // - // As a result, the key should never have generics on it. - return [ - buildItemSearchType(assocType, lowercasePaths, true).id, - buildItemSearchTypeAll(constraints, lowercasePaths), - ]; - })); - } else { - bindings = EMPTY_BINDINGS_MAP; - } - } - /** - * @type {FunctionType} - */ - let result; - if (pathIndex < 0) { - // types less than 0 are generic parameters - // the actual names of generic parameters aren't stored, since they aren't API - result = { - id: pathIndex, - ty: TY_GENERIC, - path: null, - exactPath: null, - generics, - bindings, - }; - } else if (pathIndex === 0) { - // `0` is used as a sentinel because it's fewer bytes than `null` - result = { - id: null, - ty: null, - path: null, - exactPath: null, - generics, - bindings, - }; - } else { - const item = lowercasePaths[pathIndex - 1]; - result = { - id: buildTypeMapIndex(item.name, isAssocType), - ty: item.ty, - path: item.path, - exactPath: item.exactPath, - generics, - bindings, - }; + currentResults = results.query.userQuery; + + const [ret_others, ret_in_args, ret_returned] = await Promise.all([ + addTab(results.others, results.query, true), + addTab(results.in_args, results.query, false), + addTab(results.returned, results.query, false), + ]); + + // Navigate to the relevant tab if the current tab is empty, like in case users search + // for "-> String". If they had selected another tab previously, they have to click on + // it again. + let currentTab = searchState.currentTab; + if ((currentTab === 0 && ret_others[1] === 0) || + (currentTab === 1 && ret_in_args[1] === 0) || + (currentTab === 2 && ret_returned[1] === 0)) { + if (ret_others[1] !== 0) { + currentTab = 0; + } else if (ret_in_args[1] !== 0) { + currentTab = 1; + } else if (ret_returned[1] !== 0) { + currentTab = 2; } - const cr = TYPES_POOL.get(result.id); - if (cr) { - // Shallow equality check. Since this function is used - // to construct every type object, this should be mostly - // equivalent to a deep equality check, except if there's - // a conflict, we don't keep the old one around, so it's - // not a fully precise implementation of hashcons. - if (cr.generics.length === result.generics.length && - cr.generics !== result.generics && - cr.generics.every((x, i) => result.generics[i] === x) - ) { - result.generics = cr.generics; - } - if (cr.bindings.size === result.bindings.size && cr.bindings !== result.bindings) { - let ok = true; - for (const [k, v] of cr.bindings.entries()) { - const v2 = result.bindings.get(v); - if (!v2) { - ok = false; - break; - } - if (v !== v2 && v.length === v2.length && v.every((x, i) => v2[i] === x)) { - result.bindings.set(k, v); - } else if (v !== v2) { - ok = false; - break; - } - } - if (ok) { - result.bindings = cr.bindings; - } - } - if (cr.ty === result.ty && cr.path === result.path - && cr.bindings === result.bindings && cr.generics === result.generics - && cr.ty === result.ty - ) { - return cr; - } + } + + let crates = ""; + if (rawSearchIndex.size > 1) { + crates = " in <div id=\"crate-search-div\"><select id=\"crate-search\">" + + "<option value=\"all crates\">all crates</option>"; + for (const c of rawSearchIndex.keys()) { + crates += `<option value="${c}" ${c === filterCrates && "selected"}>${c}</option>`; } - TYPES_POOL.set(result.id, result); - return result; + crates += "</select></div>"; } - /** - * Convert from RawFunctionSearchType to FunctionSearchType. - * - * Crates often have lots of functions in them, and function signatures are sometimes complex, - * so rustdoc uses a pretty tight encoding for them. This function converts it to a simpler, - * object-based encoding so that the actual search code is more readable and easier to debug. - * - * The raw function search type format is generated using serde in - * librustdoc/html/render/mod.rs: IndexItemFunctionType::write_to_string - * - * @param {Array<{name: string, ty: number}>} lowercasePaths - * - * @return {null|FunctionSearchType} - */ - function buildFunctionSearchTypeCallback(lowercasePaths) { - return functionSearchType => { - if (functionSearchType === 0) { - return null; - } - const INPUTS_DATA = 0; - const OUTPUT_DATA = 1; - let inputs, output; - if (typeof functionSearchType[INPUTS_DATA] === "number") { - inputs = [buildItemSearchType(functionSearchType[INPUTS_DATA], lowercasePaths)]; + let output = `<h1 class="search-results-title">Results${crates}</h1>`; + if (results.query.error !== null) { + const error = results.query.error; + error.forEach((value, index) => { + value = value.split("<").join("<").split(">").join(">"); + if (index % 2 !== 0) { + error[index] = `<code>${value.replaceAll(" ", " ")}</code>`; } else { - inputs = buildItemSearchTypeAll( - functionSearchType[INPUTS_DATA], - lowercasePaths, - ); + error[index] = value; } - if (functionSearchType.length > 1) { - if (typeof functionSearchType[OUTPUT_DATA] === "number") { - output = [buildItemSearchType(functionSearchType[OUTPUT_DATA], lowercasePaths)]; - } else { - output = buildItemSearchTypeAll( - functionSearchType[OUTPUT_DATA], - lowercasePaths, - ); - } - } else { - output = []; - } - const where_clause = []; - const l = functionSearchType.length; - for (let i = 2; i < l; ++i) { - where_clause.push(typeof functionSearchType[i] === "number" - ? [buildItemSearchType(functionSearchType[i], lowercasePaths)] - : buildItemSearchTypeAll(functionSearchType[i], lowercasePaths)); - } - return { - inputs, output, where_clause, - }; - }; + }); + output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`; + output += "<div id=\"search-tabs\">" + + makeTabHeader(0, "In Names", ret_others[1]) + + "</div>"; + currentTab = 0; + } else if (results.query.foundElems <= 1 && results.query.returned.length === 0) { + output += "<div id=\"search-tabs\">" + + makeTabHeader(0, "In Names", ret_others[1]) + + makeTabHeader(1, "In Parameters", ret_in_args[1]) + + makeTabHeader(2, "In Return Types", ret_returned[1]) + + "</div>"; + } else { + const signatureTabTitle = + results.query.elems.length === 0 ? "In Function Return Types" : + results.query.returned.length === 0 ? "In Function Parameters" : + "In Function Signatures"; + output += "<div id=\"search-tabs\">" + + makeTabHeader(0, signatureTabTitle, ret_others[1]) + + "</div>"; + currentTab = 0; } - /** - * Type fingerprints allow fast, approximate matching of types. - * - * This algo creates a compact representation of the type set using a Bloom filter. - * This fingerprint is used three ways: - * - * - It accelerates the matching algorithm by checking the function fingerprint against the - * query fingerprint. If any bits are set in the query but not in the function, it can't - * match. - * - * - The fourth section has the number of distinct items in the set. - * This is the distance function, used for filtering and for sorting. - * - * [^1]: Distance is the relatively naive metric of counting the number of distinct items in - * the function that are not present in the query. - * - * @param {FunctionType|QueryElement} type - a single type - * @param {Uint32Array} output - write the fingerprint to this data structure: uses 128 bits - * @param {Set<number>} fps - Set of distinct items - */ - function buildFunctionTypeFingerprint(type, output, fps) { - let input = type.id; - // All forms of `[]`/`()`/`->` get collapsed down to one thing in the bloom filter. - // Differentiating between arrays and slices, if the user asks for it, is - // still done in the matching algorithm. - if (input === typeNameIdOfArray || input === typeNameIdOfSlice) { - input = typeNameIdOfArrayOrSlice; - } - if (input === typeNameIdOfTuple || input === typeNameIdOfUnit) { - input = typeNameIdOfTupleOrUnit; - } - if (input === typeNameIdOfFn || input === typeNameIdOfFnMut || - input === typeNameIdOfFnOnce) { - input = typeNameIdOfHof; - } - // http://burtleburtle.net/bob/hash/integer.html - // ~~ is toInt32. It's used before adding, so - // the number stays in safe integer range. - const hashint1 = k => { - k = (~~k + 0x7ed55d16) + (k << 12); - k = (k ^ 0xc761c23c) ^ (k >>> 19); - k = (~~k + 0x165667b1) + (k << 5); - k = (~~k + 0xd3a2646c) ^ (k << 9); - k = (~~k + 0xfd7046c5) + (k << 3); - return (k ^ 0xb55a4f09) ^ (k >>> 16); - }; - const hashint2 = k => { - k = ~k + (k << 15); - k ^= k >>> 12; - k += k << 2; - k ^= k >>> 4; - k = Math.imul(k, 2057); - return k ^ (k >> 16); - }; - if (input !== null) { - const h0a = hashint1(input); - const h0b = hashint2(input); - // Less Hashing, Same Performance: Building a Better Bloom Filter - // doi=10.1.1.72.2442 - const h1a = ~~(h0a + Math.imul(h0b, 2)); - const h1b = ~~(h0a + Math.imul(h0b, 3)); - const h2a = ~~(h0a + Math.imul(h0b, 4)); - const h2b = ~~(h0a + Math.imul(h0b, 5)); - output[0] |= (1 << (h0a % 32)) | (1 << (h1b % 32)); - output[1] |= (1 << (h1a % 32)) | (1 << (h2b % 32)); - output[2] |= (1 << (h2a % 32)) | (1 << (h0b % 32)); - fps.add(input); - } - for (const g of type.generics) { - buildFunctionTypeFingerprint(g, output, fps); - } - const fb = { - id: null, - ty: 0, - generics: EMPTY_GENERICS_ARRAY, - bindings: EMPTY_BINDINGS_MAP, - }; - for (const [k, v] of type.bindings.entries()) { - fb.id = k; - fb.generics = v; - buildFunctionTypeFingerprint(fb, output, fps); - } - output[3] = fps.size; + if (results.query.correction !== null) { + const orig = results.query.returned.length > 0 + ? results.query.returned[0].name + : results.query.elems[0].name; + output += "<h3 class=\"search-corrections\">" + + `Type "${orig}" not found. ` + + "Showing results for closest type name " + + `"${results.query.correction}" instead.</h3>`; } - - /** - * Compare the query fingerprint with the function fingerprint. - * - * @param {{number}} fullId - The function - * @param {{Uint32Array}} queryFingerprint - The query - * @returns {number|null} - Null if non-match, number if distance - * This function might return 0! - */ - function compareTypeFingerprints(fullId, queryFingerprint) { - const fh0 = functionTypeFingerprint[fullId * 4]; - const fh1 = functionTypeFingerprint[(fullId * 4) + 1]; - const fh2 = functionTypeFingerprint[(fullId * 4) + 2]; - const [qh0, qh1, qh2] = queryFingerprint; - // Approximate set intersection with bloom filters. - // This can be larger than reality, not smaller, because hashes have - // the property that if they've got the same value, they hash to the - // same thing. False positives exist, but not false negatives. - const [in0, in1, in2] = [fh0 & qh0, fh1 & qh1, fh2 & qh2]; - // Approximate the set of items in the query but not the function. - // This might be smaller than reality, but cannot be bigger. - // - // | in_ | qh_ | XOR | Meaning | - // | --- | --- | --- | ------------------------------------------------ | - // | 0 | 0 | 0 | Not present | - // | 1 | 0 | 1 | IMPOSSIBLE because `in_` is `fh_ & qh_` | - // | 1 | 1 | 0 | If one or both is false positive, false negative | - // | 0 | 1 | 1 | Since in_ has no false negatives, must be real | - if ((in0 ^ qh0) || (in1 ^ qh1) || (in2 ^ qh2)) { - return null; - } - return functionTypeFingerprint[(fullId * 4) + 3]; - } - - class VlqHexDecoder { - constructor(string, cons) { - this.string = string; - this.cons = cons; - this.offset = 0; - this.backrefQueue = []; - } - // call after consuming `{` - decodeList() { - let c = this.string.charCodeAt(this.offset); - const ret = []; - while (c !== 125) { // 125 = "}" - ret.push(this.decode()); - c = this.string.charCodeAt(this.offset); - } - this.offset += 1; // eat cb - return ret; - } - // consumes and returns a list or integer - decode() { - let n = 0; - let c = this.string.charCodeAt(this.offset); - if (c === 123) { // 123 = "{" - this.offset += 1; - return this.decodeList(); - } - while (c < 96) { // 96 = "`" - n = (n << 4) | (c & 0xF); - this.offset += 1; - c = this.string.charCodeAt(this.offset); - } - // last character >= la - n = (n << 4) | (c & 0xF); - const [sign, value] = [n & 1, n >> 1]; - this.offset += 1; - return sign ? -value : value; - } - next() { - const c = this.string.charCodeAt(this.offset); - // sixteen characters after "0" are backref - if (c >= 48 && c < 64) { // 48 = "0", 64 = "@" - this.offset += 1; - return this.backrefQueue[c - 48]; - } - // special exception: 0 doesn't use backref encoding - // it's already one character, and it's always nullish - if (c === 96) { // 96 = "`" - this.offset += 1; - return this.cons(0); - } - const result = this.cons(this.decode()); - this.backrefQueue.unshift(result); - if (this.backrefQueue.length > 16) { - this.backrefQueue.pop(); - } - return result; - } - } - class RoaringBitmap { - constructor(str) { - const strdecoded = atob(str); - const u8array = new Uint8Array(strdecoded.length); - for (let j = 0; j < strdecoded.length; ++j) { - u8array[j] = strdecoded.charCodeAt(j); - } - const has_runs = u8array[0] === 0x3b; - const size = has_runs ? - ((u8array[2] | (u8array[3] << 8)) + 1) : - ((u8array[4] | (u8array[5] << 8) | (u8array[6] << 16) | (u8array[7] << 24))); - let i = has_runs ? 4 : 8; - let is_run; - if (has_runs) { - const is_run_len = Math.floor((size + 7) / 8); - is_run = u8array.slice(i, i + is_run_len); - i += is_run_len; - } else { - is_run = new Uint8Array(); - } - this.keys = []; - this.cardinalities = []; - for (let j = 0; j < size; ++j) { - this.keys.push(u8array[i] | (u8array[i + 1] << 8)); - i += 2; - this.cardinalities.push((u8array[i] | (u8array[i + 1] << 8)) + 1); - i += 2; - } - this.containers = []; - let offsets = null; - if (!has_runs || this.keys.length >= 4) { - offsets = []; - for (let j = 0; j < size; ++j) { - offsets.push(u8array[i] | (u8array[i + 1] << 8) | (u8array[i + 2] << 16) | - (u8array[i + 3] << 24)); - i += 4; - } - } - for (let j = 0; j < size; ++j) { - if (offsets && offsets[j] !== i) { - console.log(this.containers); - throw new Error(`corrupt bitmap ${j}: ${i} / ${offsets[j]}`); - } - if (is_run[j >> 3] & (1 << (j & 0x7))) { - const runcount = (u8array[i] | (u8array[i + 1] << 8)); - i += 2; - this.containers.push(new RoaringBitmapRun( - runcount, - u8array.slice(i, i + (runcount * 4)), - )); - i += runcount * 4; - } else if (this.cardinalities[j] >= 4096) { - this.containers.push(new RoaringBitmapBits(u8array.slice(i, i + 8192))); - i += 8192; - } else { - const end = this.cardinalities[j] * 2; - this.containers.push(new RoaringBitmapArray( - this.cardinalities[j], - u8array.slice(i, i + end), - )); - i += end; - } - } - } - contains(keyvalue) { - const key = keyvalue >> 16; - const value = keyvalue & 0xFFFF; - for (let i = 0; i < this.keys.length; ++i) { - if (this.keys[i] === key) { - return this.containers[i].contains(value); - } - } - return false; - } + if (results.query.proposeCorrectionFrom !== null) { + const orig = results.query.proposeCorrectionFrom; + const targ = results.query.proposeCorrectionTo; + output += "<h3 class=\"search-corrections\">" + + `Type "${orig}" not found and used as generic parameter. ` + + `Consider searching for "${targ}" instead.</h3>`; } - class RoaringBitmapRun { - constructor(runcount, array) { - this.runcount = runcount; - this.array = array; - } - contains(value) { - const l = this.runcount * 4; - for (let i = 0; i < l; i += 4) { - const start = this.array[i] | (this.array[i + 1] << 8); - const lenm1 = this.array[i + 2] | (this.array[i + 3] << 8); - if (value >= start && value <= (start + lenm1)) { - return true; - } - } - return false; - } + const resultsElem = document.createElement("div"); + resultsElem.id = "results"; + resultsElem.appendChild(ret_others[0]); + resultsElem.appendChild(ret_in_args[0]); + resultsElem.appendChild(ret_returned[0]); + + search.innerHTML = output; + const crateSearch = document.getElementById("crate-search"); + if (crateSearch) { + crateSearch.addEventListener("input", updateCrate); } - class RoaringBitmapArray { - constructor(cardinality, array) { - this.cardinality = cardinality; - this.array = array; - } - contains(value) { - const l = this.cardinality * 2; - for (let i = 0; i < l; i += 2) { - const start = this.array[i] | (this.array[i + 1] << 8); - if (value === start) { - return true; - } - } - return false; - } + search.appendChild(resultsElem); + // Reset focused elements. + searchState.showResults(search); + const elems = document.getElementById("search-tabs").childNodes; + searchState.focusedByTab = []; + let i = 0; + for (const elem of elems) { + const j = i; + elem.onclick = () => printTab(j); + searchState.focusedByTab.push(null); + i += 1; } - class RoaringBitmapBits { - constructor(array) { - this.array = array; - } - contains(value) { - return !!(this.array[value >> 3] & (1 << (value & 7))); - } + printTab(currentTab); +} + +function updateSearchHistory(url) { + if (!browserSupportsHistoryApi()) { + return; + } + const params = searchState.getQueryStringParams(); + if (!history.state && !params.search) { + history.pushState(null, "", url); + } else { + history.replaceState(null, "", url); } +} - /** - * Convert raw search index into in-memory search index. - * - * @param {[string, RawSearchIndexCrate][]} rawSearchIndex - */ - function buildIndex(rawSearchIndex) { - searchIndex = []; - searchIndexDeprecated = new Map(); - searchIndexEmptyDesc = new Map(); - let currentIndex = 0; - let id = 0; +/** + * Perform a search based on the current state of the search input element + * and display the results. + * @param {boolean} [forced] + */ +async function search(forced) { + const query = DocSearch.parseQuery(searchState.input.value.trim()); + let filterCrates = getFilterCrates(); - // Function type fingerprints are 128-bit bloom filters that are used to - // estimate the distance between function and query. - // This loop counts the number of items to allocate a fingerprint for. - for (const crate of rawSearchIndex.values()) { - // Each item gets an entry in the fingerprint array, and the crate - // does, too - id += crate.t.length + 1; + if (!forced && query.userQuery === currentResults) { + if (query.userQuery.length > 0) { + putBackSearch(); } - functionTypeFingerprint = new Uint32Array((id + 1) * 4); + return; + } - // This loop actually generates the search item indexes, including - // normalized names, type signature objects and fingerprints, and aliases. - id = 0; + searchState.setLoadingSearch(); - for (const [crate, crateCorpus] of rawSearchIndex) { - // a string representing the lengths of each description shard - // a string representing the list of function types - const itemDescShardDecoder = new VlqHexDecoder(crateCorpus.D, noop => noop); - let descShard = { - crate, - shard: 0, - start: 0, - len: itemDescShardDecoder.next(), - promise: null, - resolve: null, - }; - const descShardList = [ descShard ]; - - // Deprecated items and items with no description - searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); - searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); - let descIndex = 0; + const params = searchState.getQueryStringParams(); - // This object should have exactly the same set of fields as the "row" - // object defined below. Your JavaScript runtime will thank you. - // https://mathiasbynens.be/notes/shapes-ics - const crateRow = { - crate, - ty: 3, // == ExternCrate - name: crate, - path: "", - descShard, - descIndex, - exactPath: "", - desc: crateCorpus.doc, - parent: undefined, - type: null, - id, - word: crate, - normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""), - bitIndex: 0, - implDisambiguator: null, - }; - id += 1; - searchIndex.push(crateRow); - currentIndex += 1; - if (!searchIndexEmptyDesc.get(crate).contains(0)) { - descIndex += 1; - } - - // a String of one character item type codes - const itemTypes = crateCorpus.t; - // an array of (String) item names - const itemNames = crateCorpus.n; - // an array of [(Number) item index, - // (String) full path] - // an item whose index is not present will fall back to the previous present path - // i.e. if indices 4 and 11 are present, but 5-10 and 12-13 are not present, - // 5-10 will fall back to the path for 4 and 12-13 will fall back to the path for 11 - const itemPaths = new Map(crateCorpus.q); - // An array of [(Number) item index, (Number) path index] - // Used to de-duplicate inlined and re-exported stuff - const itemReexports = new Map(crateCorpus.r); - // an array of (Number) the parent path index + 1 to `paths`, or 0 if none - const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); - // a map Number, string for impl disambiguators - const implDisambiguator = new Map(crateCorpus.b); - // an array of [(Number) item type, - // (String) name] - const paths = crateCorpus.p; - // an array of [(String) alias name - // [Number] index to items] - const aliases = crateCorpus.a; + // In case we have no information about the saved crate and there is a URL query parameter, + // we override it with the URL query parameter. + if (filterCrates === null && params["filter-crate"] !== undefined) { + filterCrates = params["filter-crate"]; + } - // an array of [{name: String, ty: Number}] - const lowercasePaths = []; + // Update document title to maintain a meaningful browser history + searchState.title = "\"" + query.original + "\" Search - Rust"; - // a string representing the list of function types - const itemFunctionDecoder = new VlqHexDecoder( - crateCorpus.f, - buildFunctionSearchTypeCallback(lowercasePaths), - ); + // Because searching is incremental by character, only the most + // recent search query is added to the browser history. + updateSearchHistory(buildUrl(query.original, filterCrates)); - // convert `rawPaths` entries into object form - // generate normalizedPaths for function search mode - let len = paths.length; - let lastPath = itemPaths.get(0); - for (let i = 0; i < len; ++i) { - const elem = paths[i]; - const ty = elem[0]; - const name = elem[1]; - let path = null; - if (elem.length > 2) { - path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; - lastPath = path; - } - const exactPath = elem.length > 3 ? itemPaths.get(elem[3]) : path; + await showResults( + await docSearch.execQuery(query, filterCrates, window.currentCrate), + params.go_to_first, + filterCrates); +} - lowercasePaths.push({ty, name: name.toLowerCase(), path, exactPath}); - paths[i] = {ty, name, path, exactPath}; - } +/** + * Callback for when the search form is submitted. + * @param {Event} [e] - The event that triggered this call, if any + */ +function onSearchSubmit(e) { + e.preventDefault(); + searchState.clearInputTimeout(); + search(); +} - // convert `item*` into an object form, and construct word indices. - // - // before any analysis is performed lets gather the search terms to - // search against apart from the rest of the data. This is a quick - // operation that is cached for the life of the page state so that - // all other search operations have access to this cached data for - // faster analysis operations - lastPath = ""; - len = itemTypes.length; - let lastName = ""; - let lastWord = ""; - for (let i = 0; i < len; ++i) { - const bitIndex = i + 1; - if (descIndex >= descShard.len && - !searchIndexEmptyDesc.get(crate).contains(bitIndex)) { - descShard = { - crate, - shard: descShard.shard + 1, - start: descShard.start + descShard.len, - len: itemDescShardDecoder.next(), - promise: null, - resolve: null, - }; - descIndex = 0; - descShardList.push(descShard); - } - const name = itemNames[i] === "" ? lastName : itemNames[i]; - const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); - const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; - const type = itemFunctionDecoder.next(); - if (type !== null) { - if (type) { - const fp = functionTypeFingerprint.subarray(id * 4, (id + 1) * 4); - const fps = new Set(); - for (const t of type.inputs) { - buildFunctionTypeFingerprint(t, fp, fps); - } - for (const t of type.output) { - buildFunctionTypeFingerprint(t, fp, fps); - } - for (const w of type.where_clause) { - for (const t of w) { - buildFunctionTypeFingerprint(t, fp, fps); - } - } - } - } - // This object should have exactly the same set of fields as the "crateRow" - // object defined above. - const itemParentIdx = itemParentIdxDecoder.next(); - const row = { - crate, - ty: itemTypes.charCodeAt(i) - 65, // 65 = "A" - name, - path, - descShard, - descIndex, - exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path, - parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined, - type, - id, - word, - normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""), - bitIndex, - implDisambiguator: implDisambiguator.has(i) ? implDisambiguator.get(i) : null, - }; - id += 1; - searchIndex.push(row); - lastPath = row.path; - if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) { - descIndex += 1; - } - lastName = name; - lastWord = word; - } +function putBackSearch() { + const search_input = searchState.input; + if (!searchState.input) { + return; + } + if (search_input.value !== "" && !searchState.isDisplayed()) { + searchState.showResults(); + if (browserSupportsHistoryApi()) { + history.replaceState(null, "", + buildUrl(search_input.value, getFilterCrates())); + } + document.title = searchState.title; + } +} - if (aliases) { - const currentCrateAliases = new Map(); - ALIASES.set(crate, currentCrateAliases); - for (const alias_name in aliases) { - if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) { - continue; - } +function registerSearchEvents() { + const params = searchState.getQueryStringParams(); - let currentNameAliases; - if (currentCrateAliases.has(alias_name)) { - currentNameAliases = currentCrateAliases.get(alias_name); - } else { - currentNameAliases = []; - currentCrateAliases.set(alias_name, currentNameAliases); - } - for (const local_alias of aliases[alias_name]) { - currentNameAliases.push(local_alias + currentIndex); - } - } - } - currentIndex += itemTypes.length; - searchState.descShards.set(crate, descShardList); - } - // Drop the (rather large) hash table used for reusing function items - TYPES_POOL = new Map(); + // Populate search bar with query string search term when provided, + // but only if the input bar is empty. This avoid the obnoxious issue + // where you start trying to do a search, and the index loads, and + // suddenly your search is gone! + if (searchState.input.value === "") { + searchState.input.value = params.search || ""; } - /** - * Callback for when the search form is submitted. - * @param {Event} [e] - The event that triggered this call, if any - */ - function onSearchSubmit(e) { - e.preventDefault(); + const searchAfter500ms = () => { searchState.clearInputTimeout(); - search(); - } + if (searchState.input.value.length === 0) { + searchState.hideResults(); + } else { + searchState.timeout = setTimeout(search, 500); + } + }; + searchState.input.onkeyup = searchAfter500ms; + searchState.input.oninput = searchAfter500ms; + document.getElementsByClassName("search-form")[0].onsubmit = onSearchSubmit; + searchState.input.onchange = e => { + if (e.target !== document.activeElement) { + // To prevent doing anything when it's from a blur event. + return; + } + // Do NOT e.preventDefault() here. It will prevent pasting. + searchState.clearInputTimeout(); + // zero-timeout necessary here because at the time of event handler execution the + // pasted content is not in the input field yet. Shouldn’t make any difference for + // change, though. + setTimeout(search, 0); + }; + searchState.input.onpaste = searchState.input.onchange; - function putBackSearch() { - const search_input = searchState.input; - if (!searchState.input) { + searchState.outputElement().addEventListener("keydown", e => { + // We only handle unmodified keystrokes here. We don't want to interfere with, + // for instance, alt-left and alt-right for history navigation. + if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { return; } - if (search_input.value !== "" && !searchState.isDisplayed()) { - searchState.showResults(); - if (browserSupportsHistoryApi()) { - history.replaceState(null, "", - buildUrl(search_input.value, getFilterCrates())); - } - document.title = searchState.title; + // up and down arrow select next/previous search result, or the + // search box if we're already at the top. + if (e.which === 38) { // up + const previous = document.activeElement.previousElementSibling; + if (previous) { + previous.focus(); + } else { + searchState.focus(); + } + e.preventDefault(); + } else if (e.which === 40) { // down + const next = document.activeElement.nextElementSibling; + if (next) { + next.focus(); + } + const rect = document.activeElement.getBoundingClientRect(); + if (window.innerHeight - rect.bottom < rect.height) { + window.scrollBy(0, rect.height); + } + e.preventDefault(); + } else if (e.which === 37) { // left + nextTab(-1); + e.preventDefault(); + } else if (e.which === 39) { // right + nextTab(1); + e.preventDefault(); } - } - - function registerSearchEvents() { - const params = searchState.getQueryStringParams(); + }); - // Populate search bar with query string search term when provided, - // but only if the input bar is empty. This avoid the obnoxious issue - // where you start trying to do a search, and the index loads, and - // suddenly your search is gone! - if (searchState.input.value === "") { - searchState.input.value = params.search || ""; + searchState.input.addEventListener("keydown", e => { + if (e.which === 40) { // down + focusSearchResult(); + e.preventDefault(); } + }); - const searchAfter500ms = () => { - searchState.clearInputTimeout(); - if (searchState.input.value.length === 0) { - searchState.hideResults(); - } else { - searchState.timeout = setTimeout(search, 500); - } - }; - searchState.input.onkeyup = searchAfter500ms; - searchState.input.oninput = searchAfter500ms; - document.getElementsByClassName("search-form")[0].onsubmit = onSearchSubmit; - searchState.input.onchange = e => { - if (e.target !== document.activeElement) { - // To prevent doing anything when it's from a blur event. - return; - } - // Do NOT e.preventDefault() here. It will prevent pasting. - searchState.clearInputTimeout(); - // zero-timeout necessary here because at the time of event handler execution the - // pasted content is not in the input field yet. Shouldn’t make any difference for - // change, though. - setTimeout(search, 0); - }; - searchState.input.onpaste = searchState.input.onchange; + searchState.input.addEventListener("focus", () => { + putBackSearch(); + }); - searchState.outputElement().addEventListener("keydown", e => { - // We only handle unmodified keystrokes here. We don't want to interfere with, - // for instance, alt-left and alt-right for history navigation. - if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { - return; - } - // up and down arrow select next/previous search result, or the - // search box if we're already at the top. - if (e.which === 38) { // up - const previous = document.activeElement.previousElementSibling; - if (previous) { - previous.focus(); - } else { - searchState.focus(); - } - e.preventDefault(); - } else if (e.which === 40) { // down - const next = document.activeElement.nextElementSibling; - if (next) { - next.focus(); - } - const rect = document.activeElement.getBoundingClientRect(); - if (window.innerHeight - rect.bottom < rect.height) { - window.scrollBy(0, rect.height); - } - e.preventDefault(); - } else if (e.which === 37) { // left - nextTab(-1); - e.preventDefault(); - } else if (e.which === 39) { // right - nextTab(1); - e.preventDefault(); - } - }); + searchState.input.addEventListener("blur", () => { + searchState.input.placeholder = searchState.input.origPlaceholder; + }); - searchState.input.addEventListener("keydown", e => { - if (e.which === 40) { // down - focusSearchResult(); + // Push and pop states are used to add search results to the browser + // history. + if (browserSupportsHistoryApi()) { + // Store the previous <title> so we can revert back to it later. + const previousTitle = document.title; + + window.addEventListener("popstate", e => { + const params = searchState.getQueryStringParams(); + // Revert to the previous title manually since the History + // API ignores the title parameter. + document.title = previousTitle; + // When browsing forward to search results the previous + // search will be repeated, so the currentResults are + // cleared to ensure the search is successful. + currentResults = null; + // Synchronize search bar with query string state and + // perform the search. This will empty the bar if there's + // nothing there, which lets you really go back to a + // previous state with nothing in the bar. + if (params.search && params.search.length > 0) { + searchState.input.value = params.search; + // Some browsers fire "onpopstate" for every page load + // (Chrome), while others fire the event only when actually + // popping a state (Firefox), which is why search() is + // called both here and at the end of the startSearch() + // function. e.preventDefault(); + search(); + } else { + searchState.input.value = ""; + // When browsing back from search results the main page + // visibility must be reset. + searchState.hideResults(); } }); - - searchState.input.addEventListener("focus", () => { - putBackSearch(); - }); - - searchState.input.addEventListener("blur", () => { - searchState.input.placeholder = searchState.input.origPlaceholder; - }); - - // Push and pop states are used to add search results to the browser - // history. - if (browserSupportsHistoryApi()) { - // Store the previous <title> so we can revert back to it later. - const previousTitle = document.title; - - window.addEventListener("popstate", e => { - const params = searchState.getQueryStringParams(); - // Revert to the previous title manually since the History - // API ignores the title parameter. - document.title = previousTitle; - // When browsing forward to search results the previous - // search will be repeated, so the currentResults are - // cleared to ensure the search is successful. - currentResults = null; - // Synchronize search bar with query string state and - // perform the search. This will empty the bar if there's - // nothing there, which lets you really go back to a - // previous state with nothing in the bar. - if (params.search && params.search.length > 0) { - searchState.input.value = params.search; - // Some browsers fire "onpopstate" for every page load - // (Chrome), while others fire the event only when actually - // popping a state (Firefox), which is why search() is - // called both here and at the end of the startSearch() - // function. - e.preventDefault(); - search(); - } else { - searchState.input.value = ""; - // When browsing back from search results the main page - // visibility must be reset. - searchState.hideResults(); - } - }); - } - - // This is required in firefox to avoid this problem: Navigating to a search result - // with the keyboard, hitting enter, and then hitting back would take you back to - // the doc page, rather than the search that should overlay it. - // This was an interaction between the back-forward cache and our handlers - // that try to sync state between the URL and the search input. To work around it, - // do a small amount of re-init on page show. - window.onpageshow = () => { - const qSearch = searchState.getQueryStringParams().search; - if (searchState.input.value === "" && qSearch) { - searchState.input.value = qSearch; - } - search(); - }; } - function updateCrate(ev) { - if (ev.target.value === "all crates") { - // If we don't remove it from the URL, it'll be picked up again by the search. - const query = searchState.input.value.trim(); - updateSearchHistory(buildUrl(query, null)); + // This is required in firefox to avoid this problem: Navigating to a search result + // with the keyboard, hitting enter, and then hitting back would take you back to + // the doc page, rather than the search that should overlay it. + // This was an interaction between the back-forward cache and our handlers + // that try to sync state between the URL and the search input. To work around it, + // do a small amount of re-init on page show. + window.onpageshow = () => { + const qSearch = searchState.getQueryStringParams().search; + if (searchState.input.value === "" && qSearch) { + searchState.input.value = qSearch; } - // In case you "cut" the entry from the search input, then change the crate filter - // before paste back the previous search, you get the old search results without - // the filter. To prevent this, we need to remove the previous results. - currentResults = null; - search(true); + search(); + }; +} + +function updateCrate(ev) { + if (ev.target.value === "all crates") { + // If we don't remove it from the URL, it'll be picked up again by the search. + const query = searchState.input.value.trim(); + updateSearchHistory(buildUrl(query, null)); } + // In case you "cut" the entry from the search input, then change the crate filter + // before paste back the previous search, you get the old search results without + // the filter. To prevent this, we need to remove the previous results. + currentResults = null; + search(true); +} - buildIndex(rawSearchIndex); +function initSearch(searchIndx) { + rawSearchIndex = searchIndx; if (typeof window !== "undefined") { + docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); registerSearchEvents(); // If there's a search term in the URL, execute the search now. if (window.searchState.getQueryStringParams().search) { search(); } + } else if (typeof exports !== "undefined") { + docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); + exports.docSearch = docSearch; + exports.parseQuery = DocSearch.parseQuery; } +} - if (typeof exports !== "undefined") { - exports.initSearch = initSearch; - exports.execQuery = execQuery; - exports.parseQuery = parseQuery; - } +if (typeof exports !== "undefined") { + exports.initSearch = initSearch; } if (typeof window !== "undefined") { @@ -3897,6 +3938,4 @@ if (typeof window !== "undefined") { // exports. initSearch(new Map()); } - - })(); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index a7493d48d6a..264b7b269de 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -947,15 +947,47 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } #[inline(always)] - fn enforce_abi(_ecx: &MiriInterpCx<'tcx>) -> bool { - true - } - - #[inline(always)] fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'tcx>) -> bool { !ecx.tcx.sess.overflow_checks() } + fn check_fn_target_features( + ecx: &MiriInterpCx<'tcx>, + instance: ty::Instance<'tcx>, + ) -> InterpResult<'tcx> { + let attrs = ecx.tcx.codegen_fn_attrs(instance.def_id()); + if attrs + .target_features + .iter() + .any(|feature| !ecx.tcx.sess.target_features.contains(&feature.name)) + { + let unavailable = attrs + .target_features + .iter() + .filter(|&feature| { + !feature.implied && !ecx.tcx.sess.target_features.contains(&feature.name) + }) + .fold(String::new(), |mut s, feature| { + if !s.is_empty() { + s.push_str(", "); + } + s.push_str(feature.name.as_str()); + s + }); + let msg = format!( + "calling a function that requires unavailable target features: {unavailable}" + ); + // On WASM, this is not UB, but instead gets rejected during validation of the module + // (see #84988). + if ecx.tcx.sess.target.is_like_wasm { + throw_machine_stop!(TerminationInfo::Abort(msg)); + } else { + throw_ub_format!("{msg}"); + } + } + Ok(()) + } + #[inline(always)] fn find_mir_or_eval_fn( ecx: &mut MiriInterpCx<'tcx>, @@ -1060,6 +1092,10 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.generate_nan(inputs) } + fn ub_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { + Ok(ecx.tcx.sess.ub_checks()) + } + fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'tcx>, def_id: DefId, diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs index c85c0ebe244..312b7ba05d3 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::mem::MaybeUninit; use std::ptr::null_mut; diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs index 9e2a430dd94..f1f308b37e7 100644 --- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs +++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs @@ -1,7 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -Zmiri-disable-stacked-borrows // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -#![feature(new_uninit)] use std::ptr::null_mut; use std::sync::atomic::{AtomicPtr, Ordering}; diff --git a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs index 54bea6c6908..79c97a5b752 100644 --- a/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs +++ b/src/tools/miri/tests/fail/weak_memory/weak_uninit.rs @@ -6,7 +6,6 @@ // run multiple times until one try returns true. // Spurious failure is possible, if you are really unlucky with // the RNG and always read the latest value from the store buffer. -#![feature(new_uninit)] use std::sync::atomic::*; use std::thread::spawn; diff --git a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs b/src/tools/miri/tests/panic/target_feature_wasm.rs index 5056f32de44..c67d2983f78 100644 --- a/src/tools/miri/tests/pass/function_calls/target_feature_wasm.rs +++ b/src/tools/miri/tests/panic/target_feature_wasm.rs @@ -2,7 +2,9 @@ //@compile-flags: -C target-feature=-simd128 fn main() { - // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 + // Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. + // But if the compiler actually uses the target feature, it will lead to an error when the module is loaded. + // We emulate this with an "unsupported" error. assert!(!cfg!(target_feature = "simd128")); simd128_fn(); } diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs index b1470dabc26..ce01e611b2c 100644 --- a/src/tools/miri/tests/pass/rc.rs +++ b/src/tools/miri/tests/pass/rc.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(get_mut_unchecked)] #![allow(ambiguous_wide_pointer_comparisons)] diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs index 0b9805681b4..459d04d6761 100644 --- a/src/tools/miri/tests/pass/slices.rs +++ b/src/tools/miri/tests/pass/slices.rs @@ -1,7 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance -#![feature(new_uninit)] #![feature(slice_as_chunks)] #![feature(slice_partition_dedup)] #![feature(layout_for_ptr)] diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 3b859fe98c5..1394675a9dc 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -690,6 +690,7 @@ dependencies = [ "mdbook", "once_cell", "pathdiff", + "pulldown-cmark", "regex", "semver", "serde_json", diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 43a22f358c3..e162ba033cc 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -427,7 +427,6 @@ function loadSearchJS(doc_folder, resource_suffix) { return list[descIndex]; }, loadedDescShard: function(crate, shard, data) { - //console.log(this.descShards); this.descShards.get(crate)[shard].resolve(data.split("\n")); }, }; @@ -436,15 +435,15 @@ function loadSearchJS(doc_folder, resource_suffix) { const searchJs = fs.readdirSync(staticFiles).find(f => f.match(/search.*\.js$/)); const searchModule = require(path.join(staticFiles, searchJs)); searchModule.initSearch(searchIndex.searchIndex); - + const docSearch = searchModule.docSearch; return { doSearch: function(queryStr, filterCrate, currentCrate) { - return searchModule.execQuery(searchModule.parseQuery(queryStr), + return docSearch.execQuery(searchModule.parseQuery(queryStr), filterCrate, currentCrate); }, getCorrections: function(queryStr, filterCrate, currentCrate) { const parsedQuery = searchModule.parseQuery(queryStr); - searchModule.execQuery(parsedQuery, filterCrate, currentCrate); + docSearch.execQuery(parsedQuery, filterCrate, currentCrate); return parsedQuery.correction; }, parseQuery: searchModule.parseQuery, diff --git a/tests/assembly/struct-target-features.rs b/tests/assembly/struct-target-features.rs new file mode 100644 index 00000000000..cc86fbaa840 --- /dev/null +++ b/tests/assembly/struct-target-features.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -O +//@ assembly-output: emit-asm +//@ only-x86_64 + +#![crate_type = "lib"] +#![feature(struct_target_features)] + +// Check that a struct_target_features type causes the compiler to effectively inline intrinsics. + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "fma")] +struct Fma {} + +pub fn add_simple(_: Avx, v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 { + // CHECK-NOT: call + // CHECK: vaddps + unsafe { _mm256_add_ps(v, v) } +} + +pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) { + // CHECK-NOT: call + // CHECK-DAG: vaddps + let r1 = unsafe { _mm256_add_ps(v, v) }; + // CHECK-DAG: vfmadd213ps + let r2 = unsafe { _mm256_fmadd_ps(v, v, v) }; + (r1, r2) +} diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 34e52d38bbe..db76aae3dd0 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64 -// FIXME: Add `-Cllvm-args=--lint-abort-on-error` after LLVM 19 -//@ compile-flags: -O -C no-prepopulate-passes -C passes=lint +//@ min-llvm-version: 19 +//@ compile-flags: -O -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: arm diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index a4b7c0caa6d..ae8d8383f5b 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,5 +1,6 @@ //@ revisions: linux apple -//@ compile-flags: -C opt-level=0 -C no-prepopulate-passes -C passes=lint +//@ min-llvm-version: 19 +//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs new file mode 100644 index 00000000000..d5faac44836 --- /dev/null +++ b/tests/codegen/naked-fn/aligned.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 +//@ needs-asm-support +//@ ignore-arm no "ret" mnemonic + +#![crate_type = "lib"] +#![feature(naked_functions, fn_align)] +use std::arch::asm; + +// CHECK: Function Attrs: naked +// CHECK-NEXT: define{{.*}}void @naked_empty() +// CHECK: align 16 +#[repr(align(16))] +#[no_mangle] +#[naked] +pub unsafe extern "C" fn naked_empty() { + // CHECK-NEXT: start: + // CHECK-NEXT: call void asm + // CHECK-NEXT: unreachable + asm!("ret", options(noreturn)); +} diff --git a/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs b/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs new file mode 100644 index 00000000000..5833b832ba4 --- /dev/null +++ b/tests/codegen/sanitizer/riscv64-shadow-call-stack.rs @@ -0,0 +1,17 @@ +//@ compile-flags: --target riscv64imac-unknown-none-elf -Zsanitizer=shadow-call-stack +//@ needs-llvm-components: riscv + +#![allow(internal_features)] +#![crate_type = "rlib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +// CHECK: ; Function Attrs:{{.*}}shadowcallstack +// CHECK: define dso_local void @foo() unnamed_addr #0 +#[no_mangle] +pub fn foo() {} + +// CHECK: attributes #0 = {{.*}}shadowcallstack{{.*}} diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b4596ae2cb..1b2b63c3d1a 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -3,21 +3,21 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 -// The "+v8a" feature is matched as optional as it isn't added when we -// are targeting older LLVM versions. Once the min supported version -// is LLVM-14 we can remove the optional regex matching for this feature. +// The "+fpmr" feature is matched as optional as it is only an explicit +// feature in LLVM 18. Once the min supported version is LLVM-19 the optional +// regex matching for this feature can be removed. //@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0 -// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } +// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/crashes/123693.rs b/tests/crashes/123693.rs index c2e192092be..c3236322c6e 100644 --- a/tests/crashes/123693.rs +++ b/tests/crashes/123693.rs @@ -3,11 +3,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::NOTHING }>, + Dst: TransmuteFrom<Src, { Assume::NOTHING }>, { } } diff --git a/tests/crashes/124207.rs b/tests/crashes/124207.rs index a4e1c551890..a11eedb140a 100644 --- a/tests/crashes/124207.rs +++ b/tests/crashes/124207.rs @@ -4,6 +4,6 @@ trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; trait AnotherTrait {} -impl<T: std::mem::BikeshedIntrinsicFrom<(), ()>> AnotherTrait for T {} +impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {} impl AnotherTrait for OpaqueType {} pub fn main() {} diff --git a/tests/crashes/125881.rs b/tests/crashes/125881.rs index 98331d3c974..a38f1891b61 100644 --- a/tests/crashes/125881.rs +++ b/tests/crashes/125881.rs @@ -3,6 +3,6 @@ #![feature(transmutability)] #![feature(unboxed_closures,effects)] -const fn test() -> impl std::mem::BikeshedIntrinsicFrom() { +const fn test() -> impl std::mem::TransmuteFrom() { || {} } diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs index c0604b90a67..728578179ed 100644 --- a/tests/crashes/126267.rs +++ b/tests/crashes/126267.rs @@ -14,11 +14,11 @@ pub enum Error { } mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, // safety is NOT assumed + Dst: TransmuteFrom<Src>, // safety is NOT assumed { } } diff --git a/tests/crashes/126377.rs b/tests/crashes/126377.rs index f8b9b693b65..f6727bcc0a4 100644 --- a/tests/crashes/126377.rs +++ b/tests/crashes/126377.rs @@ -4,7 +4,7 @@ #![feature(generic_const_exprs)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -15,7 +15,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { } >, diff --git a/tests/crashes/126966.rs b/tests/crashes/126966.rs index edeedc68c40..2c9f1a70f4f 100644 --- a/tests/crashes/126966.rs +++ b/tests/crashes/126966.rs @@ -1,10 +1,10 @@ //@ known-bug: rust-lang/rust#126966 mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } diff --git a/tests/run-make/dos-device-input/rmake.rs b/tests/run-make/dos-device-input/rmake.rs index dee3b86f095..f5911d78fd9 100644 --- a/tests/run-make/dos-device-input/rmake.rs +++ b/tests/run-make/dos-device-input/rmake.rs @@ -1,13 +1,11 @@ //@ only-windows // Reason: dos devices are a Windows thing -use std::path::Path; - -use run_make_support::{rustc, static_lib_name}; +use run_make_support::{path, rustc, static_lib_name}; fn main() { rustc().input(r"\\.\NUL").crate_type("staticlib").run(); rustc().input(r"\\?\NUL").crate_type("staticlib").run(); - assert!(Path::new(&static_lib_name("rust_out")).exists()); + assert!(path(&static_lib_name("rust_out")).exists()); } diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index e5482af10bb..c8c113ce944 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -5,9 +5,7 @@ // `all-shared` should only emit files that can be shared between crates. // See https://github.com/rust-lang/rust/pull/83478 -use std::path::Path; - -use run_make_support::{has_extension, has_prefix, rustdoc, shallow_find_files}; +use run_make_support::{has_extension, has_prefix, path, rustdoc, shallow_find_files}; fn main() { rustdoc() @@ -19,17 +17,18 @@ fn main() { .args(&["--extend-css", "z.css"]) .input("x.rs") .run(); - assert!(Path::new("invocation-only/search-index-xxx.js").exists()); - assert!(Path::new("invocation-only/settings.html").exists()); - assert!(Path::new("invocation-only/x/all.html").exists()); - assert!(Path::new("invocation-only/x/index.html").exists()); - assert!(Path::new("invocation-only/theme-xxx.css").exists()); // generated from z.css - assert!(!Path::new("invocation-only/storage-xxx.js").exists()); - assert!(!Path::new("invocation-only/SourceSerif4-It.ttf.woff2").exists()); + assert!(path("invocation-only/search-index-xxx.js").exists()); + assert!(path("invocation-only/crates-xxx.js").exists()); + assert!(path("invocation-only/settings.html").exists()); + assert!(path("invocation-only/x/all.html").exists()); + assert!(path("invocation-only/x/index.html").exists()); + assert!(path("invocation-only/theme-xxx.css").exists()); // generated from z.css + assert!(!path("invocation-only/storage-xxx.js").exists()); + assert!(!path("invocation-only/SourceSerif4-It.ttf.woff2").exists()); // FIXME: this probably shouldn't have a suffix - assert!(Path::new("invocation-only/y-xxx.css").exists()); + assert!(path("invocation-only/y-xxx.css").exists()); // FIXME: this is technically incorrect (see `write_shared`) - assert!(!Path::new("invocation-only/main-xxx.js").exists()); + assert!(!path("invocation-only/main-xxx.js").exists()); rustdoc() .arg("-Zunstable-options") @@ -60,10 +59,10 @@ fn main() { .len(), 1 ); - assert!(!Path::new("toolchain-only/search-index-xxx.js").exists()); - assert!(!Path::new("toolchain-only/x/index.html").exists()); - assert!(!Path::new("toolchain-only/theme.css").exists()); - assert!(!Path::new("toolchain-only/y-xxx.css").exists()); + assert!(!path("toolchain-only/search-index-xxx.js").exists()); + assert!(!path("toolchain-only/x/index.html").exists()); + assert!(!path("toolchain-only/theme.css").exists()); + assert!(!path("toolchain-only/y-xxx.css").exists()); rustdoc() .arg("-Zunstable-options") @@ -87,11 +86,11 @@ fn main() { .len(), 1 ); - assert!(!Path::new("all-shared/search-index-xxx.js").exists()); - assert!(!Path::new("all-shared/settings.html").exists()); - assert!(!Path::new("all-shared/x").exists()); - assert!(!Path::new("all-shared/src").exists()); - assert!(!Path::new("all-shared/theme.css").exists()); + assert!(!path("all-shared/search-index-xxx.js").exists()); + assert!(!path("all-shared/settings.html").exists()); + assert!(!path("all-shared/x").exists()); + assert!(!path("all-shared/src").exists()); + assert!(!path("all-shared/theme.css").exists()); assert_eq!( shallow_find_files("all-shared/static.files", |path| { has_prefix(path, "main-") && has_extension(path, "js") @@ -99,5 +98,5 @@ fn main() { .len(), 1 ); - assert!(!Path::new("all-shared/y-xxx.css").exists()); + assert!(!path("all-shared/y-xxx.css").exists()); } diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs index be0eeaf1717..5decd802b34 100644 --- a/tests/run-make/libtest-thread-limit/rmake.rs +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -11,6 +11,9 @@ // Reason: thread limit modification //@ ignore-cross-compile // Reason: this test fails armhf-gnu, reasons unknown +//@ needs-unwind +// Reason: this should be ignored in cg_clif (Cranelift) CI and anywhere +// else that uses panic=abort. use std::ffi::{self, CStr, CString}; use std::path::PathBuf; diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs index 9085b6c7bc2..9f480ec6b6a 100644 --- a/tests/run-make/manual-crate-name/rmake.rs +++ b/tests/run-make/manual-crate-name/rmake.rs @@ -1,8 +1,6 @@ -use std::path::Path; - -use run_make_support::rustc; +use run_make_support::{path, rustc}; fn main() { rustc().input("bar.rs").crate_name("foo").run(); - assert!(Path::new("libfoo.rlib").is_file()); + assert!(path("libfoo.rlib").is_file()); } diff --git a/tests/run-make/native-lib-alt-naming/native.rs b/tests/run-make/native-lib-alt-naming/native.rs new file mode 100644 index 00000000000..6c869e74cd2 --- /dev/null +++ b/tests/run-make/native-lib-alt-naming/native.rs @@ -0,0 +1,2 @@ +#[no_mangle] +pub extern "C" fn native_lib_alt_naming() {} diff --git a/tests/run-make/native-lib-alt-naming/rmake.rs b/tests/run-make/native-lib-alt-naming/rmake.rs new file mode 100644 index 00000000000..d1ea0fc8687 --- /dev/null +++ b/tests/run-make/native-lib-alt-naming/rmake.rs @@ -0,0 +1,15 @@ +// On MSVC the alternative naming format for static libraries (`libfoo.a`) is accepted in addition +// to the default format (`foo.lib`). + +//REMOVE@ only-msvc + +use run_make_support::rustc; + +fn main() { + // Prepare the native library. + rustc().input("native.rs").crate_type("staticlib").output("libnative.a").run(); + + // Try to link to it from both a rlib and a bin. + rustc().input("rust.rs").crate_type("rlib").arg("-lstatic=native").run(); + rustc().input("rust.rs").crate_type("bin").arg("-lstatic=native").run(); +} diff --git a/tests/run-make/native-lib-alt-naming/rust.rs b/tests/run-make/native-lib-alt-naming/rust.rs new file mode 100644 index 00000000000..da0f5d925d1 --- /dev/null +++ b/tests/run-make/native-lib-alt-naming/rust.rs @@ -0,0 +1 @@ +pub fn main() {} diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs index 5d422085834..24ae6bc2456 100644 --- a/tests/run-make/pretty-print-with-dep-file/rmake.rs +++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs @@ -5,14 +5,12 @@ // does not get an unexpected dep-info file. // See https://github.com/rust-lang/rust/issues/112898 -use std::path::Path; - -use run_make_support::{invalid_utf8_contains, rfs, rustc}; +use run_make_support::{invalid_utf8_contains, path, rfs, rustc}; fn main() { rustc().emit("dep-info").arg("-Zunpretty=expanded").input("with-dep.rs").run(); invalid_utf8_contains("with-dep.d", "with-dep.rs"); rfs::remove_file("with-dep.d"); rustc().emit("dep-info").arg("-Zunpretty=normal").input("with-dep.rs").run(); - assert!(!Path::new("with-dep.d").exists()); + assert!(!path("with-dep.d").exists()); } diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs index 4c6f9c19091..4287ab0a931 100644 --- a/tests/run-make/profile/rmake.rs +++ b/tests/run-make/profile/rmake.rs @@ -8,16 +8,14 @@ //@ ignore-cross-compile //@ needs-profiler-support -use std::path::Path; - -use run_make_support::{run, rustc}; +use run_make_support::{path, run, rustc}; fn main() { rustc().arg("-g").arg("-Zprofile").input("test.rs").run(); run("test"); - assert!(Path::new("test.gcno").exists(), "no .gcno file"); - assert!(Path::new("test.gcda").exists(), "no .gcda file"); + assert!(path("test.gcno").exists(), "no .gcno file"); + assert!(path("test.gcda").exists(), "no .gcda file"); rustc().arg("-g").arg("-Zprofile").arg("-Zprofile-emit=abc/abc.gcda").input("test.rs").run(); run("test"); - assert!(Path::new("abc/abc.gcda").exists(), "gcda file not emitted to defined path"); + assert!(path("abc/abc.gcda").exists(), "gcda file not emitted to defined path"); } diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs index 118b3a666ad..bdc90e39f9e 100644 --- a/tests/run-make/reset-codegen-1/rmake.rs +++ b/tests/run-make/reset-codegen-1/rmake.rs @@ -7,9 +7,7 @@ //@ ignore-cross-compile -use std::path::Path; - -use run_make_support::{bin_name, rustc}; +use run_make_support::{bin_name, path, rustc}; fn compile(output_file: &str, emit: Option<&str>) { let mut rustc = rustc(); @@ -34,10 +32,10 @@ fn main() { // In the None case, bin_name is required for successful Windows compilation. let output_file = &bin_name(output_file); compile(output_file, emit); - assert!(Path::new(output_file).is_file()); + assert!(path(output_file).is_file()); } compile("multi-output", Some("asm,obj")); - assert!(Path::new("multi-output.s").is_file()); - assert!(Path::new("multi-output.o").is_file()); + assert!(path("multi-output.s").is_file()); + assert!(path("multi-output.o").is_file()); } diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs index ce088508178..5a030c6f496 100644 --- a/tests/run-make/rustdoc-determinism/rmake.rs +++ b/tests/run-make/rustdoc-determinism/rmake.rs @@ -1,16 +1,14 @@ // Assert that the search index is generated deterministically, regardless of the // order that crates are documented in. -use std::path::Path; - -use run_make_support::{diff, rustdoc}; +use run_make_support::{diff, path, rustdoc}; fn main() { - let foo_first = Path::new("foo_first"); + let foo_first = path("foo_first"); rustdoc().input("foo.rs").out_dir(&foo_first).run(); rustdoc().input("bar.rs").out_dir(&foo_first).run(); - let bar_first = Path::new("bar_first"); + let bar_first = path("bar_first"); rustdoc().input("bar.rs").out_dir(&bar_first).run(); rustdoc().input("foo.rs").out_dir(&bar_first).run(); diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs index 181239eac4d..7f6accf26c2 100644 --- a/tests/run-make/rustdoc-output-path/rmake.rs +++ b/tests/run-make/rustdoc-output-path/rmake.rs @@ -1,11 +1,9 @@ // Checks that if the output folder doesn't exist, rustdoc will create it. -use std::path::Path; - -use run_make_support::rustdoc; +use run_make_support::{path, rustdoc}; fn main() { - let out_dir = Path::new("foo/bar/doc"); + let out_dir = path("foo/bar/doc"); rustdoc().input("foo.rs").out_dir(&out_dir).run(); assert!(out_dir.exists()); } diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs new file mode 100644 index 00000000000..c7d952ae567 --- /dev/null +++ b/tests/rustdoc-json/traits/self.rs @@ -0,0 +1,58 @@ +// ignore-tidy-linelength + +pub struct Foo; + +// Check that Self is represented uniformly between inherent impls, trait impls, +// and trait definitions, even though it uses both SelfTyParam and SelfTyAlias +// internally. +// +// Each assertion matches 3 times, and should be the same each time. + +impl Foo { + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + pub fn by_ref(&self) {} + + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' true true true + pub fn by_exclusive_ref(&mut self) {} + + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' + pub fn by_value(self) {} + + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + pub fn with_lifetime<'a>(&'a self) {} + + //@ ismany '$.index[*][?(@.name=="build")].inner.function.decl.output.generic' '"Self"' '"Self"' '"Self"' + pub fn build() -> Self { + Self + } +} + +pub struct Bar; + +pub trait SelfParams { + fn by_ref(&self); + fn by_exclusive_ref(&mut self); + fn by_value(self); + fn with_lifetime<'a>(&'a self); + fn build() -> Self; +} + +impl SelfParams for Bar { + fn by_ref(&self) {} + fn by_exclusive_ref(&mut self) {} + fn by_value(self) {} + fn with_lifetime<'a>(&'a self) {} + fn build() -> Self { + Self + } +} diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.rs b/tests/ui/asm/naked-with-invalid-repr-attr.rs new file mode 100644 index 00000000000..687fe1ad73d --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.rs @@ -0,0 +1,48 @@ +//@ needs-asm-support +#![feature(naked_functions)] +#![feature(fn_align)] +#![crate_type = "lib"] +use std::arch::asm; + +#[repr(C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example1() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(transparent)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example2() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(align(16), C)] +//~^ ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example3() { + //~^ NOTE not a struct, enum, or union + unsafe { asm!("", options(noreturn)) } +} + +// note: two errors because of packed and C +#[repr(C, packed)] +//~^ ERROR attribute should be applied to a struct or union [E0517] +//~| ERROR attribute should be applied to a struct, enum, or union [E0517] +#[naked] +extern "C" fn example4() { + //~^ NOTE not a struct, enum, or union + //~| NOTE not a struct or union + unsafe { asm!("", options(noreturn)) } +} + +#[repr(u8)] +//~^ ERROR attribute should be applied to an enum [E0517] +#[naked] +extern "C" fn example5() { + //~^ NOTE not an enum + unsafe { asm!("", options(noreturn)) } +} diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.stderr b/tests/ui/asm/naked-with-invalid-repr-attr.stderr new file mode 100644 index 00000000000..3740f17a9dc --- /dev/null +++ b/tests/ui/asm/naked-with-invalid-repr-attr.stderr @@ -0,0 +1,77 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:7:8 + | +LL | #[repr(C)] + | ^ +... +LL | / extern "C" fn example1() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:15:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +... +LL | / extern "C" fn example2() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:23:19 + | +LL | #[repr(align(16), C)] + | ^ +... +LL | / extern "C" fn example3() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:8 + | +LL | #[repr(C, packed)] + | ^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/naked-with-invalid-repr-attr.rs:32:11 + | +LL | #[repr(C, packed)] + | ^^^^^^ +... +LL | / extern "C" fn example4() { +LL | | +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not a struct or union + +error[E0517]: attribute should be applied to an enum + --> $DIR/naked-with-invalid-repr-attr.rs:42:8 + | +LL | #[repr(u8)] + | ^^ +... +LL | / extern "C" fn example5() { +LL | | +LL | | unsafe { asm!("", options(noreturn)) } +LL | | } + | |_- not an enum + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr new file mode 100644 index 00000000000..a0d7fa5c3c9 --- /dev/null +++ b/tests/ui/cfg/disallowed-cli-cfgs.fmt_debug_.stderr @@ -0,0 +1,8 @@ +error: unexpected `--cfg fmt_debug="shallow"` flag + | + = note: config `fmt_debug` is only supposed to be controlled by `-Z fmt-debug` + = note: manually setting a built-in cfg can and does create incoherent behaviors + = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs index 714c01f4bc6..3c9ee87f28a 100644 --- a/tests/ui/cfg/disallowed-cli-cfgs.rs +++ b/tests/ui/cfg/disallowed-cli-cfgs.rs @@ -6,6 +6,7 @@ //@ revisions: target_pointer_width_ target_vendor_ target_has_atomic_ //@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_ //@ revisions: target_thread_local_ relocation_model_ +//@ revisions: fmt_debug_ //@ [overflow_checks_]compile-flags: --cfg overflow_checks //@ [debug_assertions_]compile-flags: --cfg debug_assertions @@ -31,5 +32,6 @@ //@ [target_has_atomic_load_store_]compile-flags: --cfg target_has_atomic_load_store="32" //@ [target_thread_local_]compile-flags: --cfg target_thread_local //@ [relocation_model_]compile-flags: --cfg relocation_model="a" +//@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow" fn main() {} diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index b311a80c8fd..b1a9c5810d8 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE` LL | #[cfg(FALSE)] | ^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(FALSE)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr index 9ab3290ef22..0b01b1da5a7 100644 --- a/tests/ui/check-cfg/cargo-build-script.stderr +++ b/tests/ui/check-cfg/cargo-build-script.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `has_foo` LL | #[cfg(has_foo)] | ^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index 9d3117ed54d..6de6e9a6851 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index 14e24cb1429..d4a7f6defb2 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr index 08bd43832ea..831722a12e2 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value` LL | #[cfg(value)] | ^^^^^ | - = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(value)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr index 6db1144eada..a35a8d68def 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value` LL | #[cfg(my_value)] | ^^^^^^^^ | - = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(my_value)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr index a5f8176343a..65a73ffcd1d 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `linux` LL | #[cfg(linux)] | ^^^^^ help: found config with similar value: `target_os = "linux"` | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(linux)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr index 6fecdb52362..536c992ee92 100644 --- a/tests/ui/check-cfg/compact-names.stderr +++ b/tests/ui/check-cfg/compact-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture` LL | #[cfg(target(os = "linux", architecture = "arm"))] | ^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index 2497864e87e..6c26a8b11d9 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index a7d4c6d4df6..b7ccf5e5f83 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index a7d4c6d4df6..b7ccf5e5f83 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr index 7ac3241db5f..5350534f3e8 100644 --- a/tests/ui/check-cfg/exhaustive-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 520cffc4b02..a163728b51d 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu` LL | #[cfg_attr(uu, test)] | ^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(uu)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 239 more = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr index e8b61d808fe..98f09a648bc 100644 --- a/tests/ui/check-cfg/stmt-no-ice.stderr +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom` LL | #[cfg(crossbeam_loom)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index 41130210df1..abcf53cfe30 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -18,7 +18,7 @@ warning: unexpected `cfg` condition name: `features` LL | #[cfg(features = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index d5fe7464792..1fda4b2089e 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -16,6 +16,7 @@ #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_target_thread_local)] #![feature(cfg_ub_checks)] +#![feature(fmt_debug)] // This part makes sure that none of the well known names are // unexpected. @@ -33,6 +34,8 @@ //~^ WARN unexpected `cfg` condition value doctest = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value + fmt_debug = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value miri = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value overflow_checks = "_UNEXPECTED_VALUE", diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 103a7564a0f..0530e1c34c9 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:28:5 + --> $DIR/well-known-values.rs:29:5 | LL | clippy = "_UNEXPECTED_VALUE", | ^^^^^^---------------------- @@ -11,7 +11,7 @@ LL | clippy = "_UNEXPECTED_VALUE", = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:30:5 + --> $DIR/well-known-values.rs:31:5 | LL | debug_assertions = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^---------------------- @@ -22,7 +22,7 @@ LL | debug_assertions = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:32:5 + --> $DIR/well-known-values.rs:33:5 | LL | doc = "_UNEXPECTED_VALUE", | ^^^---------------------- @@ -33,7 +33,7 @@ LL | doc = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:34:5 + --> $DIR/well-known-values.rs:35:5 | LL | doctest = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -44,7 +44,16 @@ LL | doctest = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:36:5 + --> $DIR/well-known-values.rs:37:5 + | +LL | fmt_debug = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `fmt_debug` are: `full`, `none`, and `shallow` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:39:5 | LL | miri = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -55,7 +64,7 @@ LL | miri = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:38:5 + --> $DIR/well-known-values.rs:41:5 | LL | overflow_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^---------------------- @@ -66,7 +75,7 @@ LL | overflow_checks = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:40:5 + --> $DIR/well-known-values.rs:43:5 | LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,7 +84,7 @@ LL | panic = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:42:5 + --> $DIR/well-known-values.rs:45:5 | LL | proc_macro = "_UNEXPECTED_VALUE", | ^^^^^^^^^^---------------------- @@ -86,7 +95,7 @@ LL | proc_macro = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:44:5 + --> $DIR/well-known-values.rs:47:5 | LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +104,7 @@ LL | relocation_model = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:46:5 + --> $DIR/well-known-values.rs:49:5 | LL | rustfmt = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -106,7 +115,7 @@ LL | rustfmt = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:48:5 + --> $DIR/well-known-values.rs:51:5 | LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -115,7 +124,7 @@ LL | sanitize = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:50:5 + --> $DIR/well-known-values.rs:53:5 | LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,7 +133,7 @@ LL | target_abi = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:52:5 + --> $DIR/well-known-values.rs:55:5 | LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +142,7 @@ LL | target_arch = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:54:5 + --> $DIR/well-known-values.rs:57:5 | LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +151,7 @@ LL | target_endian = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:56:5 + --> $DIR/well-known-values.rs:59:5 | LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +160,7 @@ LL | target_env = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:58:5 + --> $DIR/well-known-values.rs:61:5 | LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,16 +169,16 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:60:5 + --> $DIR/well-known-values.rs:63:5 | LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:62:5 + --> $DIR/well-known-values.rs:65:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +187,7 @@ LL | target_has_atomic = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:64:5 + --> $DIR/well-known-values.rs:67:5 | LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,7 +196,7 @@ LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:66:5 + --> $DIR/well-known-values.rs:69:5 | LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +205,7 @@ LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:68:5 + --> $DIR/well-known-values.rs:71:5 | LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +214,7 @@ LL | target_os = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:70:5 + --> $DIR/well-known-values.rs:73:5 | LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +223,7 @@ LL | target_pointer_width = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:72:5 + --> $DIR/well-known-values.rs:75:5 | LL | target_thread_local = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^---------------------- @@ -225,7 +234,7 @@ LL | target_thread_local = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:74:5 + --> $DIR/well-known-values.rs:77:5 | LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -234,7 +243,7 @@ LL | target_vendor = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:76:5 + --> $DIR/well-known-values.rs:79:5 | LL | test = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -245,7 +254,7 @@ LL | test = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:78:5 + --> $DIR/well-known-values.rs:81:5 | LL | ub_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^---------------------- @@ -256,7 +265,7 @@ LL | ub_checks = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:80:5 + --> $DIR/well-known-values.rs:83:5 | LL | unix = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -267,7 +276,7 @@ LL | unix = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:82:5 + --> $DIR/well-known-values.rs:85:5 | LL | windows = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -278,7 +287,7 @@ LL | windows = "_UNEXPECTED_VALUE", = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:88:7 + --> $DIR/well-known-values.rs:91:7 | LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | ^^^^^^^^^^^^------- @@ -288,5 +297,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration -warning: 29 warnings emitted +warning: 30 warnings emitted diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs index 569e57fa326..401267a0f16 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs @@ -4,11 +4,11 @@ #![allow(incomplete_features, unstable_features)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>() where - Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, + Dst: TransmuteFrom<Src, Context, ASSUME>, //~^ ERROR trait takes at most 2 generic arguments but 3 generic arguments were supplied { } diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr index 5c04c4c9d5b..96716685614 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr @@ -1,8 +1,8 @@ error[E0107]: trait takes at most 2 generic arguments but 3 generic arguments were supplied --> $DIR/transmutable-ice-110969.rs:11:14 | -LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, - | ^^^^^^^^^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument +LL | Dst: TransmuteFrom<Src, Context, ASSUME>, + | ^^^^^^^^^^^^^ -------- help: remove the unnecessary generic argument | | | expected at most 2 generic arguments diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.rs b/tests/ui/consts/const-eval/const_fn_target_feature.rs index ee669abb51e..8db41ba11c0 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature.rs @@ -1,6 +1,7 @@ //@ only-x86_64 // Set the base cpu explicitly, in case the default has been changed. //@ compile-flags: -C target-cpu=x86-64 -C target-feature=+ssse3 +//@ check-pass #![crate_type = "lib"] @@ -9,7 +10,8 @@ const A: () = unsafe { ssse3_fn() }; // error (avx2 not enabled at compile time) const B: () = unsafe { avx2_fn() }; -//~^ ERROR evaluation of constant value failed +// FIXME: currently we do not detect this UB, since we don't want the result of const-eval +// to depend on `tcx.sess` which can differ between crates in a crate graph. #[target_feature(enable = "ssse3")] const unsafe fn ssse3_fn() {} diff --git a/tests/ui/consts/const-eval/const_fn_target_feature.stderr b/tests/ui/consts/const-eval/const_fn_target_feature.stderr deleted file mode 100644 index d3a00b57ebb..00000000000 --- a/tests/ui/consts/const-eval/const_fn_target_feature.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/const_fn_target_feature.rs:11:24 - | -LL | const B: () = unsafe { avx2_fn() }; - | ^^^^^^^^^ calling a function that requires unavailable target features: avx2 - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs index deed09e4b2a..8ddfe61943c 100644 --- a/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs +++ b/tests/ui/consts/const-eval/const_fn_target_feature_wasm.rs @@ -7,7 +7,9 @@ #[cfg(target_feature = "simd128")] compile_error!("simd128 target feature should be disabled"); -// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988 +// Calling functions with `#[target_feature]` is not unsound on WASM, see #84988. +// (It can still lead to a runtime error though so we'd be in our right to abort execution, +// just not to declare it UB.) const A: () = simd128_fn(); #[target_feature(enable = "simd128")] diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.rs b/tests/ui/deriving/deriving-smart-pointer-expanded.rs index b78258c2529..e48ad3dd4bc 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.rs +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.rs @@ -20,3 +20,9 @@ where data: &'a mut T, x: core::marker::PhantomData<X>, } + +#[derive(SmartPointer)] +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout index 3c7e7198180..68ef17f2b05 100644 --- a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout @@ -42,3 +42,18 @@ impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> + MyTrait<__S>> ::core::ops::CoerceUnsized<MyPointer2<'a, Y, Z, __S, X>> for MyPointer2<'a, Y, Z, T, X> where Y: MyTrait<T>, Y: MyTrait<__S> { } + +#[repr(transparent)] +struct MyPointerWithoutPointee<'a, T: ?Sized> { + ptr: &'a T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for + MyPointerWithoutPointee<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized<MyPointerWithoutPointee<'a, __S>> for + MyPointerWithoutPointee<'a, T> { +} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index 04f52a154fe..f02fb56130f 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -10,13 +10,6 @@ enum NotStruct<'a, T: ?Sized> { } #[derive(SmartPointer)] -//~^ ERROR: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits -#[repr(transparent)] -struct NoPointee<'a, T: ?Sized> { - ptr: &'a T, -} - -#[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field #[repr(transparent)] struct NoField<'a, #[pointee] T: ?Sized> {} @@ -31,6 +24,23 @@ struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); //~| ERROR: type parameter `T` is never used #[derive(SmartPointer)] +//~^ ERROR: `SmartPointer` can only be derived on `struct`s that are generic over at least one type +#[repr(transparent)] +struct NoGeneric<'a>(&'a u8); + +#[derive(SmartPointer)] +//~^ ERROR: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits +#[repr(transparent)] +struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> { + a: (&'a T1, &'a T2), +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); +//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + +#[derive(SmartPointer)] //~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` struct NotTransparent<'a, #[pointee] T: ?Sized> { ptr: &'a T, diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index 8b0f91d41fb..e7c2afc8b00 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -6,7 +6,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits +error: `SmartPointer` can only be derived on `struct`s with at least one field --> $DIR/deriving-smart-pointer-neg.rs:12:10 | LL | #[derive(SmartPointer)] @@ -22,7 +22,7 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) -error: `SmartPointer` can only be derived on `struct`s with at least one field +error: `SmartPointer` can only be derived on `struct`s that are generic over at least one type --> $DIR/deriving-smart-pointer-neg.rs:26:10 | LL | #[derive(SmartPointer)] @@ -30,8 +30,22 @@ LL | #[derive(SmartPointer)] | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) +error: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:31:10 + | +LL | #[derive(SmartPointer)] + | ^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits + --> $DIR/deriving-smart-pointer-neg.rs:40:39 + | +LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B)); + | ^ ^ + error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` - --> $DIR/deriving-smart-pointer-neg.rs:33:10 + --> $DIR/deriving-smart-pointer-neg.rs:43:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -39,13 +53,13 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `derive(SmartPointer)` requires T to be marked `?Sized` - --> $DIR/deriving-smart-pointer-neg.rs:41:36 + --> $DIR/deriving-smart-pointer-neg.rs:51:36 | LL | struct NoMaybeSized<'a, #[pointee] T> { | ^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:16 + --> $DIR/deriving-smart-pointer-neg.rs:15:16 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^^ unused lifetime parameter @@ -53,7 +67,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:22:31 + --> $DIR/deriving-smart-pointer-neg.rs:15:31 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^ unused type parameter @@ -61,7 +75,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:20 + --> $DIR/deriving-smart-pointer-neg.rs:22:20 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^^ unused lifetime parameter @@ -69,13 +83,13 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:29:35 + --> $DIR/deriving-smart-pointer-neg.rs:22:35 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/feature-gates/feature-gate-fmt-debug.rs b/tests/ui/feature-gates/feature-gate-fmt-debug.rs new file mode 100644 index 00000000000..f30befbd19c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fmt-debug.rs @@ -0,0 +1,5 @@ +#[cfg(fmt_debug = "full")] +//~^ ERROR is experimental +fn main() { + +} diff --git a/tests/ui/feature-gates/feature-gate-fmt-debug.stderr b/tests/ui/feature-gates/feature-gate-fmt-debug.stderr new file mode 100644 index 00000000000..9ced0b8facf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fmt-debug.stderr @@ -0,0 +1,13 @@ +error[E0658]: `cfg(fmt_debug)` is experimental and subject to change + --> $DIR/feature-gate-fmt-debug.rs:1:7 + | +LL | #[cfg(fmt_debug = "full")] + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #129709 <https://github.com/rust-lang/rust/issues/129709> for more information + = help: add `#![feature(fmt_debug)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.rs b/tests/ui/feature-gates/feature-gate-struct-target-features.rs new file mode 100644 index 00000000000..85494881146 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.rs @@ -0,0 +1,4 @@ +#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition +struct Avx {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr new file mode 100644 index 00000000000..1e18d3ee1e1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr @@ -0,0 +1,10 @@ +error: attribute should be applied to a function definition + --> $DIR/feature-gate-struct-target-features.rs:1:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | struct Avx {} + | ------------- not a function definition + +error: aborting due to 1 previous error + diff --git a/tests/ui/fmt/fmt_debug/full.rs b/tests/ui/fmt/fmt_debug/full.rs new file mode 100644 index 00000000000..4e9384d2c52 --- /dev/null +++ b/tests/ui/fmt/fmt_debug/full.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Zfmt-debug=full +//@ run-pass +#![feature(fmt_debug)] +#![allow(dead_code)] +#![allow(unused)] + +#[derive(Debug)] +struct Foo { + bar: u32, +} + +fn main() { + let s = format!("Still works: {:?} '{:?}'", cfg!(fmt_debug = "full"), Foo { bar: 1 }); + assert_eq!("Still works: true 'Foo { bar: 1 }'", s); +} diff --git a/tests/ui/fmt/fmt_debug/invalid.rs b/tests/ui/fmt/fmt_debug/invalid.rs new file mode 100644 index 00000000000..09cb46f1ea6 --- /dev/null +++ b/tests/ui/fmt/fmt_debug/invalid.rs @@ -0,0 +1,4 @@ +//@ compile-flags: -Zfmt-debug=invalid-value +//@ failure-status: 1 +fn main() { +} diff --git a/tests/ui/fmt/fmt_debug/invalid.stderr b/tests/ui/fmt/fmt_debug/invalid.stderr new file mode 100644 index 00000000000..fa6c9380744 --- /dev/null +++ b/tests/ui/fmt/fmt_debug/invalid.stderr @@ -0,0 +1,2 @@ +error: incorrect value `invalid-value` for unstable option `fmt-debug` - either `full`, `shallow`, or `none` was expected + diff --git a/tests/ui/fmt/fmt_debug/none.rs b/tests/ui/fmt/fmt_debug/none.rs new file mode 100644 index 00000000000..f45d37d9da2 --- /dev/null +++ b/tests/ui/fmt/fmt_debug/none.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -Zfmt-debug=none +//@ run-pass +#![feature(fmt_debug)] +#![allow(dead_code)] +#![allow(unused)] + +#[derive(Debug)] +struct Foo { + bar: u32, +} + +#[derive(Debug)] +enum Baz { + Quz, +} + +#[cfg(fmt_debug = "full")] +compile_error!("nope"); + +#[cfg(fmt_debug = "none")] +struct Custom; + +impl std::fmt::Debug for Custom { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("custom_fmt") + } +} + +fn main() { + let c = Custom; + let s = format!("Debug is '{:?}', '{:#?}', and '{c:?}'", Foo { bar: 1 }, Baz::Quz); + assert_eq!("Debug is '', '', and ''", s); + + let f = 3.0; + let s = format_args!("{:?}x{:#?}y{f:?}", 1234, "can't debug this").to_string(); + assert_eq!("xy", s); +} diff --git a/tests/ui/fmt/fmt_debug/shallow.rs b/tests/ui/fmt/fmt_debug/shallow.rs new file mode 100644 index 00000000000..479cd1b8875 --- /dev/null +++ b/tests/ui/fmt/fmt_debug/shallow.rs @@ -0,0 +1,33 @@ +//@ compile-flags: -Zfmt-debug=shallow +//@ run-pass +#![feature(fmt_debug)] +#![allow(dead_code)] +#![allow(unused)] + +#[derive(Debug)] +struct Foo { + bar: u32, + bomb: Bomb, +} + +#[derive(Debug)] +enum Baz { + Quz, +} + +struct Bomb; + +impl std::fmt::Debug for Bomb { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + panic!() + } +} + +fn main() { + let s = format!("Debug is '{:?}' and '{:#?}'", Foo { bar: 1, bomb: Bomb }, Baz::Quz); + assert_eq!("Debug is 'Foo' and 'Quz'", s); + + let f = 3.0; + let s = format_args!("{:?}{:#?}{f:?}", 1234, cfg!(fmt_debug = "shallow")).to_string(); + assert_eq!("1234true3.0", s); +} diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.rs b/tests/ui/inference/detect-old-time-version-format_description-parse.rs new file mode 100644 index 00000000000..453a795e768 --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.rs @@ -0,0 +1,8 @@ +#![crate_name = "time"] + +fn main() { + let items = Box::new(vec![]); //~ ERROR E0282 + //~^ NOTE type must be known at this point + //~| NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` + items.into(); +} diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr new file mode 100644 index 00000000000..2949a5dcfec --- /dev/null +++ b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed for `Box<Vec<_>>` + --> $DIR/detect-old-time-version-format_description-parse.rs:4:9 + | +LL | let items = Box::new(vec![]); + | ^^^^^ ---------------- type must be known at this point + | + = note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index ab46fd796c5..99f98c3f27a 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -13,5 +13,13 @@ const RAW_EQ_PTR: bool = unsafe { //~| unable to turn pointer into integer }; +const RAW_EQ_NOT_ALIGNED: bool = unsafe { + let arr = [0u8; 4]; + let aref = &*arr.as_ptr().cast::<i32>(); + std::intrinsics::raw_eq(aref, aref) +//~^ ERROR evaluation of constant value failed +//~| alignment +}; + pub fn main() { } diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index af16c2bc64a..bedfc8283ea 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -13,6 +13,12 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/intrinsic-raw_eq-const-bad.rs:19:5 + | +LL | std::intrinsics::raw_eq(aref, aref) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/patterns-dont-match-nt-statement.rs b/tests/ui/pattern/patterns-dont-match-nt-statement.rs new file mode 100644 index 00000000000..c8d41459383 --- /dev/null +++ b/tests/ui/pattern/patterns-dont-match-nt-statement.rs @@ -0,0 +1,19 @@ +//@ check-pass + +// Make sure that a `stmt` nonterminal does not eagerly match against +// a `pat`, since this will always cause a parse error... + +macro_rules! m { + ($pat:pat) => {}; + ($stmt:stmt) => {}; +} + +macro_rules! m2 { + ($stmt:stmt) => { + m! { $stmt } + }; +} + +m2! { let x = 1 } + +fn main() {} diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 94d79d56c59..5c4fb847932 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-ermsb_target_feature // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature +// gate-test-aarch64_unstable_target_feature // gate-test-csky_target_feature // gate-test-loongarch_target_feature // gate-test-lahfsahf_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index a69020e6864..37c5ed01688 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:26:18 + --> $DIR/gate.rs:27:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs new file mode 100644 index 00000000000..feb479b6dc8 --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.rs @@ -0,0 +1,98 @@ +//@ only-x86_64 +#![feature(struct_target_features)] +//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes +#![feature(target_feature_11)] + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx")] +//~^ ERROR attribute should be applied to a function definition or unit struct +struct Invalid(u32); + +#[target_feature(enable = "avx")] +struct Avx {} + +#[target_feature(enable = "sse")] +struct Sse(); + +#[target_feature(enable = "avx")] +fn avx() {} + +trait TFAssociatedType { + type Assoc; +} + +impl TFAssociatedType for () { + type Assoc = Avx; +} + +fn avx_self(_: <() as TFAssociatedType>::Assoc) { + avx(); +} + +fn avx_avx(_: Avx) { + avx(); +} + +extern "C" fn bad_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI + +#[inline(always)] +//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]` +fn inline_fun(_: Avx) {} +//~^ ERROR cannot use a struct with target features in a #[inline(always)] function + +trait Simd { + fn do_something(&self); +} + +impl Simd for Avx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +impl Simd for Sse { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm_setzero_ps()); + } + } +} + +struct WithAvx { + #[allow(dead_code)] + avx: Avx, +} + +impl Simd for WithAvx { + fn do_something(&self) { + unsafe { + println!("{:?}", _mm256_setzero_ps()); + } + } +} + +#[inline(never)] +fn dosomething<S: Simd>(simd: &S) { + simd.do_something(); +} + +fn avxfn(_: &Avx) {} + +fn main() { + Avx {}; + //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133] + + if is_x86_feature_detected!("avx") { + let avx = unsafe { Avx {} }; + avxfn(&avx); + dosomething(&avx); + dosomething(&WithAvx { avx }); + } + if is_x86_feature_detected!("sse") { + dosomething(&unsafe { Sse {} }) + } +} diff --git a/tests/ui/target-feature/struct-target-features.stderr b/tests/ui/target-feature/struct-target-features.stderr new file mode 100644 index 00000000000..5ef863f504e --- /dev/null +++ b/tests/ui/target-feature/struct-target-features.stderr @@ -0,0 +1,47 @@ +warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/struct-target-features.rs:2:12 + | +LL | #![feature(struct_target_features)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: attribute should be applied to a function definition or unit struct + --> $DIR/struct-target-features.rs:8:1 + | +LL | #[target_feature(enable = "avx")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Invalid(u32); + | -------------------- not a function definition or a unit struct + +error: cannot use a struct with target features in a function with non-Rust ABI + --> $DIR/struct-target-features.rs:37:1 + | +LL | extern "C" fn bad_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a struct with target features in a #[inline(always)] function + --> $DIR/struct-target-features.rs:42:1 + | +LL | fn inline_fun(_: Avx) {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/struct-target-features.rs:40:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block + --> $DIR/struct-target-features.rs:86:5 + | +LL | Avx {}; + | ^^^^^^ initializing type with `target_feature` attr + | + = note: this struct can only be constructed if the corresponding `target_feature`s are available + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs index 213fd008cd3..e965bac5713 100644 --- a/tests/ui/threads-sendsync/child-outlives-parent.rs +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -6,8 +6,8 @@ use std::thread; -fn child2(_s: String) { } +fn child2(_s: String) {} pub fn main() { - let _x = thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move || child2("hi".to_string())); } diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs index 67790367e27..9d5ac4b16aa 100644 --- a/tests/ui/threads-sendsync/clone-with-exterior.rs +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -7,14 +7,15 @@ use std::thread; struct Pair { a: isize, - b: isize + b: isize, } pub fn main() { - let z: Box<_> = Box::new(Pair { a : 10, b : 12}); + let z: Box<_> = Box::new(Pair { a: 10, b: 12 }); - thread::spawn(move|| { + thread::spawn(move || { assert_eq!(z.a, 10); assert_eq!(z.b, 12); - }).join(); + }) + .join(); } diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs index 0c37fda8a39..3eb68707e78 100644 --- a/tests/ui/threads-sendsync/comm.rs +++ b/tests/ui/threads-sendsync/comm.rs @@ -2,12 +2,12 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move || { child(&tx) }); + let t = thread::spawn(move || child(&tx)); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 1ea862f1e7d..99c6c4a5e12 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -2,14 +2,15 @@ //@ needs-threads //@ ignore-sgx no processes -use std::thread; -use std::env; use std::process::Command; +use std::{env, thread}; struct Handle(i32); impl Drop for Handle { - fn drop(&mut self) { panic!(); } + fn drop(&mut self) { + panic!(); + } } thread_local!(static HANDLE: Handle = Handle(0)); @@ -19,14 +20,15 @@ fn main() { if args.len() == 1 { let out = Command::new(&args[0]).arg("test").output().unwrap(); let stderr = std::str::from_utf8(&out.stderr).unwrap(); - assert!(stderr.contains("explicit panic"), - "bad failure message:\n{}\n", stderr); + assert!(stderr.contains("explicit panic"), "bad failure message:\n{}\n", stderr); } else { // TLS dtors are not always run on process exit thread::spawn(|| { HANDLE.with(|h| { println!("{}", h.0); }); - }).join().unwrap(); + }) + .join() + .unwrap(); } } diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs index fbbd6b02a06..5ce27faed76 100644 --- a/tests/ui/threads-sendsync/issue-29488.rs +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -19,5 +19,7 @@ fn main() { thread::spawn(|| { FOO.with(|_| {}); println!("test1"); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs index aa2de51974b..5652ad7de55 100644 --- a/tests/ui/threads-sendsync/issue-4446.rs +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -9,7 +9,10 @@ pub fn main() { tx.send("hello, world").unwrap(); - thread::spawn(move|| { + thread::spawn(move || { println!("{}", rx.recv().unwrap()); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs index b8324a8c43f..1adebd1e252 100644 --- a/tests/ui/threads-sendsync/issue-4448.rs +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -7,7 +7,7 @@ use std::thread; pub fn main() { let (tx, rx) = channel::<&'static str>(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { assert_eq!(rx.recv().unwrap(), "hello, world"); }); diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs index fa07a4ebc7d..57fc87db768 100644 --- a/tests/ui/threads-sendsync/issue-8827.rs +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -1,12 +1,12 @@ //@ run-pass //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Receiver}; +use std::thread; fn periodical(n: isize) -> Receiver<bool> { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { loop { for _ in 1..n { match chan.send(false) { @@ -16,7 +16,7 @@ fn periodical(n: isize) -> Receiver<bool> { } match chan.send(true) { Ok(()) => {} - Err(..) => break + Err(..) => break, } } }); @@ -25,7 +25,7 @@ fn periodical(n: isize) -> Receiver<bool> { fn integers() -> Receiver<isize> { let (chan, port) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut i = 1; loop { match chan.send(i) { @@ -47,7 +47,7 @@ fn main() { (_, true, true) => println!("FizzBuzz"), (_, true, false) => println!("Fizz"), (_, false, true) => println!("Buzz"), - (i, false, false) => println!("{}", i) + (i, false, false) => println!("{}", i), } } } diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs index 6b5907e5c1d..b532ddf104d 100644 --- a/tests/ui/threads-sendsync/issue-9396.rs +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -3,12 +3,12 @@ #![allow(deprecated)] //@ needs-threads -use std::sync::mpsc::{TryRecvError, channel}; +use std::sync::mpsc::{channel, TryRecvError}; use std::thread; pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move||{ + let t = thread::spawn(move || { thread::sleep_ms(10); tx.send(()).unwrap(); }); @@ -16,7 +16,7 @@ pub fn main() { match rx.try_recv() { Ok(()) => break, Err(TryRecvError::Empty) => {} - Err(TryRecvError::Disconnected) => unreachable!() + Err(TryRecvError::Disconnected) => unreachable!(), } } t.join(); diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs index f5354c60bfc..fe0b47f3a84 100644 --- a/tests/ui/threads-sendsync/mpsc_stress.rs +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -2,18 +2,12 @@ //@ compile-flags:--test //@ needs-threads -use std::sync::mpsc::channel; -use std::sync::mpsc::TryRecvError; -use std::sync::mpsc::RecvError; -use std::sync::mpsc::RecvTimeoutError; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::{channel, RecvError, RecvTimeoutError, TryRecvError}; use std::sync::Arc; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; - use std::thread; use std::time::Duration; - /// Simple thread synchronization utility struct Barrier { // Not using mutex/condvar for precision @@ -42,7 +36,6 @@ impl Barrier { } } - fn shared_close_sender_does_not_lose_messages_iter() { let (tb, rb) = Barrier::new2(); @@ -71,7 +64,6 @@ fn shared_close_sender_does_not_lose_messages() { }); } - // https://github.com/rust-lang/rust/issues/39364 fn concurrent_recv_timeout_and_upgrade_iter() { // 1 us @@ -85,8 +77,8 @@ fn concurrent_recv_timeout_and_upgrade_iter() { match rx.recv_timeout(sleep) { Ok(_) => { break; - }, - Err(_) => {}, + } + Err(_) => {} } } }); @@ -105,7 +97,6 @@ fn concurrent_recv_timeout_and_upgrade() { }); } - fn concurrent_writes_iter() { const THREADS: usize = 4; const PER_THR: usize = 100; diff --git a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs index b943b0c433d..dd02166c0fa 100644 --- a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs +++ b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs @@ -1,12 +1,13 @@ //@ run-pass #![allow(unused_imports)] -use std::thread; use std::sync::Mutex; +use std::thread; fn par_for<I, F>(iter: I, f: F) - where I: Iterator, - I::Item: Send, - F: Fn(I::Item) + Sync +where + I: Iterator, + I::Item: Send, + F: Fn(I::Item) + Sync, { for item in iter { f(item) @@ -15,9 +16,7 @@ fn par_for<I, F>(iter: I, f: F) fn sum(x: &[i32]) { let sum_lengths = Mutex::new(0); - par_for(x.windows(4), |x| { - *sum_lengths.lock().unwrap() += x.len() - }); + par_for(x.windows(4), |x| *sum_lengths.lock().unwrap() += x.len()); assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4); } @@ -26,9 +25,7 @@ fn main() { let mut elements = [0; 20]; // iterators over references into this stack frame - par_for(elements.iter_mut().enumerate(), |(i, x)| { - *x = i as i32 - }); + par_for(elements.iter_mut().enumerate(), |(i, x)| *x = i as i32); sum(&elements) } diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs index 3e1532b3132..c02a3717d3d 100644 --- a/tests/ui/threads-sendsync/send-resource.rs +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -6,11 +6,11 @@ //@ pretty-expanded FIXME #23616 //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; struct test { - f: isize, + f: isize, } impl Drop for test { @@ -18,15 +18,13 @@ impl Drop for test { } fn test(f: isize) -> test { - test { - f: f - } + test { f: f } } pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { + let t = thread::spawn(move || { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/tests/ui/threads-sendsync/send-type-inference.rs b/tests/ui/threads-sendsync/send-type-inference.rs index 287b3d567ae..7608c19b575 100644 --- a/tests/ui/threads-sendsync/send-type-inference.rs +++ b/tests/ui/threads-sendsync/send-type-inference.rs @@ -9,11 +9,11 @@ use std::sync::mpsc::{channel, Sender}; // tests that ctrl's type gets inferred properly struct Command<K, V> { key: K, - val: V + val: V, } -fn cache_server<K:Send+'static,V:Send+'static>(mut tx: Sender<Sender<Command<K, V>>>) { +fn cache_server<K: Send + 'static, V: Send + 'static>(mut tx: Sender<Sender<Command<K, V>>>) { let (tx1, _rx) = channel(); tx.send(tx1); } -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/threads-sendsync/send_str_hashmap.rs b/tests/ui/threads-sendsync/send_str_hashmap.rs index 9cbb0bed447..2675b162190 100644 --- a/tests/ui/threads-sendsync/send_str_hashmap.rs +++ b/tests/ui/threads-sendsync/send_str_hashmap.rs @@ -1,9 +1,7 @@ //@ run-pass -use std::collections::HashMap; use std::borrow::Cow; - -use std::borrow::Cow::Borrowed as B; -use std::borrow::Cow::Owned as O; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::HashMap; type SendStr = Cow<'static, str>; diff --git a/tests/ui/threads-sendsync/send_str_treemap.rs b/tests/ui/threads-sendsync/send_str_treemap.rs index cc1f560f69b..3e0eace3399 100644 --- a/tests/ui/threads-sendsync/send_str_treemap.rs +++ b/tests/ui/threads-sendsync/send_str_treemap.rs @@ -1,8 +1,7 @@ //@ run-pass -use std::collections::BTreeMap; use std::borrow::Cow; - -use std::borrow::Cow::{Owned as O, Borrowed as B}; +use std::borrow::Cow::{Borrowed as B, Owned as O}; +use std::collections::BTreeMap; type SendStr = Cow<'static, str>; @@ -51,8 +50,8 @@ fn main() { assert_eq!(map.get(&O("def".to_string())), Some(&d)); assert!(map.remove(&B("foo")).is_some()); - assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) - .collect::<Vec<String>>() - .concat(), - "abc50bcd51cde52def53".to_string()); + assert_eq!( + map.into_iter().map(|(k, v)| format!("{}{}", k, v)).collect::<Vec<String>>().concat(), + "abc50bcd51cde52def53".to_string() + ); } diff --git a/tests/ui/threads-sendsync/sendable-class.rs b/tests/ui/threads-sendsync/sendable-class.rs index 3ee1b60a04a..8e5e76d826a 100644 --- a/tests/ui/threads-sendsync/sendable-class.rs +++ b/tests/ui/threads-sendsync/sendable-class.rs @@ -11,15 +11,12 @@ use std::sync::mpsc::channel; struct foo { - i: isize, - j: char, + i: isize, + j: char, } -fn foo(i:isize, j: char) -> foo { - foo { - i: i, - j: j - } +fn foo(i: isize, j: char) -> foo { + foo { i: i, j: j } } pub fn main() { diff --git a/tests/ui/threads-sendsync/sendfn-is-a-block.rs b/tests/ui/threads-sendsync/sendfn-is-a-block.rs index f01b440424a..9afa1c47b65 100644 --- a/tests/ui/threads-sendsync/sendfn-is-a-block.rs +++ b/tests/ui/threads-sendsync/sendfn-is-a-block.rs @@ -1,7 +1,9 @@ //@ run-pass - -fn test<F>(f: F) -> usize where F: FnOnce(usize) -> usize { +fn test<F>(f: F) -> usize +where + F: FnOnce(usize) -> usize, +{ return f(22); } diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 63cf3ff4049..79a71e968f9 100644 --- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -3,19 +3,24 @@ use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start<F:FnOnce(isize)>(f: F) { +fn test05_start<F: FnOnce(isize)>(f: F) { f(22); } fn test05() { let three: Box<_> = Box::new(3); - let fn_to_send = move|n:isize| { + let fn_to_send = move |n: isize| { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); }; - thread::spawn(move|| { + thread::spawn(move || { test05_start(fn_to_send); - }).join().ok().unwrap(); + }) + .join() + .ok() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs index e4d83b53f3c..558c2d515aa 100644 --- a/tests/ui/threads-sendsync/spawn-fn.rs +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -10,9 +10,9 @@ fn x(s: String, n: isize) { } pub fn main() { - let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); - let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); - let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); + let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65)); + let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66)); + let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67)); let mut i = 30; while i > 0 { i = i - 1; diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs index 2a7a9e2f497..e53385aa714 100644 --- a/tests/ui/threads-sendsync/spawn-types.rs +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -4,13 +4,13 @@ //@ needs-threads /* - Make sure we can spawn tasks that take different types of - parameters. This is based on a test case for #520 provided by Rob - Arnold. - */ + Make sure we can spawn tasks that take different types of + parameters. This is based on a test case for #520 provided by Rob + Arnold. +*/ -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; type ctx = Sender<isize>; @@ -20,6 +20,6 @@ fn iotask(_tx: &ctx, ip: String) { pub fn main() { let (tx, _rx) = channel::<isize>(); - let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); + let t = thread::spawn(move || iotask(&tx, "localhost".to_string())); t.join().ok().unwrap(); } diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs index c7b344b9f75..c9f7c40ddb8 100644 --- a/tests/ui/threads-sendsync/spawn.rs +++ b/tests/ui/threads-sendsync/spawn.rs @@ -4,7 +4,10 @@ use std::thread; pub fn main() { - thread::spawn(move|| child(10)).join().ok().unwrap(); + thread::spawn(move || child(10)).join().ok().unwrap(); } -fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); } +fn child(i: isize) { + println!("{}", i); + assert_eq!(i, 10); +} diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs index 8278fec1885..02dff2a3483 100644 --- a/tests/ui/threads-sendsync/spawn2.rs +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -4,7 +4,7 @@ use std::thread; pub fn main() { - let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + let t = thread::spawn(move || child((10, 20, 30, 40, 50, 60, 70, 80, 90))); t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug } diff --git a/tests/ui/threads-sendsync/sync-send-in-std.rs b/tests/ui/threads-sendsync/sync-send-in-std.rs index 3a97cbb0c68..ddf026236a8 100644 --- a/tests/ui/threads-sendsync/sync-send-in-std.rs +++ b/tests/ui/threads-sendsync/sync-send-in-std.rs @@ -6,8 +6,16 @@ use std::net::ToSocketAddrs; -fn is_sync<T>(_: T) where T: Sync {} -fn is_send<T>(_: T) where T: Send {} +fn is_sync<T>(_: T) +where + T: Sync, +{ +} +fn is_send<T>(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs index 3b8fdb60acf..51d5e294b38 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs @@ -3,18 +3,20 @@ #![allow(warnings)] #![feature(drain, collections_bound, btree_range)] -use std::collections::BinaryHeap; -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::LinkedList; -use std::collections::VecDeque; -use std::collections::HashMap; -use std::collections::HashSet; - +use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::mem; use std::ops::Bound::Included; -fn is_sync<T>(_: T) where T: Sync {} -fn is_send<T>(_: T) where T: Send {} +fn is_sync<T>(_: T) +where + T: Sync, +{ +} +fn is_send<T>(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $($iter:ident),+) => ({ diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs index 4c77b5d2ad8..512c81a85fc 100644 --- a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -5,8 +5,16 @@ use std::iter::{empty, once, repeat}; -fn is_sync<T>(_: T) where T: Sync {} -fn is_send<T>(_: T) where T: Send {} +fn is_sync<T>(_: T) +where + T: Sync, +{ +} +fn is_send<T>(_: T) +where + T: Send, +{ +} macro_rules! all_sync_send { ($ctor:expr, $iter:ident) => ({ @@ -43,12 +51,12 @@ macro_rules! all_sync_send_mutable_ref { } macro_rules! is_sync_send { - ($ctor:expr) => ({ + ($ctor:expr) => {{ let x = $ctor; is_sync(x); let y = $ctor; is_send(y); - }) + }}; } fn main() { @@ -63,24 +71,26 @@ fn main() { let a = [1]; let b = [2]; - all_sync_send!(a.iter(), - cloned, - cycle, - chain([2].iter()), - zip([2].iter()), - map(|_| 1), - filter(|_| true), - filter_map(|_| Some(1)), - enumerate, - peekable, - skip_while(|_| true), - take_while(|_| true), - skip(1), - take(1), - scan(1, |_, _| Some(1)), - flat_map(|_| b.iter()), - fuse, - inspect(|_| ())); + all_sync_send!( + a.iter(), + cloned, + cycle, + chain([2].iter()), + zip([2].iter()), + map(|_| 1), + filter(|_| true), + filter_map(|_| Some(1)), + enumerate, + peekable, + skip_while(|_| true), + take_while(|_| true), + skip(1), + take(1), + scan(1, |_, _| Some(1)), + flat_map(|_| b.iter()), + fuse, + inspect(|_| ()) + ); is_sync_send!((1..).step_by(2)); is_sync_send!((1..2).step_by(2)); diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs index 50f2b591894..c4fe36e770d 100644 --- a/tests/ui/threads-sendsync/task-comm-0.rs +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -2,12 +2,14 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test05(); } +pub fn main() { + test05(); +} -fn test05_start(tx : &Sender<isize>) { +fn test05_start(tx: &Sender<isize>) { tx.send(10).unwrap(); println!("sent 10"); tx.send(20).unwrap(); @@ -18,7 +20,7 @@ fn test05_start(tx : &Sender<isize>) { fn test05() { let (tx, rx) = channel(); - let t = thread::spawn(move|| { test05_start(&tx) }); + let t = thread::spawn(move || test05_start(&tx)); let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs index 41592bd916b..75d9e887cd1 100644 --- a/tests/ui/threads-sendsync/task-comm-1.rs +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -4,11 +4,15 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start() { println!("Started / Finished task."); } +fn start() { + println!("Started / Finished task."); +} fn test00() { - thread::spawn(move|| start() ).join(); + thread::spawn(move || start()).join(); println!("Completing."); } diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs index 844652c0dde..44c31aeed77 100644 --- a/tests/ui/threads-sendsync/task-comm-10.rs +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -3,8 +3,8 @@ #![allow(unused_mut)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; fn start(tx: &Sender<Sender<String>>) { let (tx2, rx) = channel(); @@ -22,7 +22,7 @@ fn start(tx: &Sender<Sender<String>>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { start(&tx) }); + let child = thread::spawn(move || start(&tx)); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs index 199082fda96..7c349c716fa 100644 --- a/tests/ui/threads-sendsync/task-comm-11.rs +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -13,9 +13,7 @@ fn start(tx: &Sender<Sender<isize>>) { pub fn main() { let (tx, rx) = channel(); - let child = thread::spawn(move|| { - start(&tx) - }); + let child = thread::spawn(move || start(&tx)); let _tx = rx.recv().unwrap(); child.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs index 7be7ec4c988..95c5d5c45ef 100644 --- a/tests/ui/threads-sendsync/task-comm-12.rs +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -5,15 +5,17 @@ use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn start(_task_number: isize) { println!("Started / Finished task."); } +fn start(_task_number: isize) { + println!("Started / Finished task."); +} fn test00() { let i: isize = 0; - let mut result = thread::spawn(move|| { - start(i) - }); + let mut result = thread::spawn(move || start(i)); // Sleep long enough for the thread to finish. let mut i = 0_usize; diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs index 414e6e0db76..88ea3cbff08 100644 --- a/tests/ui/threads-sendsync/task-comm-13.rs +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -7,12 +7,15 @@ use std::thread; fn start(tx: &Sender<isize>, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(start + i).unwrap(); + i += 1; + } } pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = thread::spawn(move|| { start(&tx, 0, 10) }).join(); + let _ = thread::spawn(move || start(&tx, 0, 10)).join(); println!("Joined task"); } diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs index 54deb221294..ff4ffd2968d 100644 --- a/tests/ui/threads-sendsync/task-comm-14.rs +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -13,7 +13,10 @@ pub fn main() { while (i > 0) { println!("{}", i); let tx = tx.clone(); - thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::spawn({ + let i = i; + move || child(i, &tx) + }); i = i - 1; } diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs index f487bf3cc84..1308446893b 100644 --- a/tests/ui/threads-sendsync/task-comm-15.rs +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -20,9 +20,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let t = thread::spawn(move|| { - start(&tx, 10) - }); + let t = thread::spawn(move || start(&tx, 10)); rx.recv(); t.join(); } diff --git a/tests/ui/threads-sendsync/task-comm-16.rs b/tests/ui/threads-sendsync/task-comm-16.rs index 3b0fec11acd..e76f7bedc93 100644 --- a/tests/ui/threads-sendsync/task-comm-16.rs +++ b/tests/ui/threads-sendsync/task-comm-16.rs @@ -3,15 +3,19 @@ #![allow(unused_parens)] #![allow(non_camel_case_types)] -use std::sync::mpsc::channel; use std::cmp; +use std::sync::mpsc::channel; // Tests of ports and channels on various types fn test_rec() { - struct R {val0: isize, val1: u8, val2: char} + struct R { + val0: isize, + val1: u8, + val2: char, + } let (tx, rx) = channel(); - let r0: R = R {val0: 0, val1: 1, val2: '2'}; + let r0: R = R { val0: 0, val1: 1, val2: '2' }; tx.send(r0).unwrap(); let mut r1: R; r1 = rx.recv().unwrap(); @@ -45,34 +49,29 @@ fn test_str() { enum t { tag1, tag2(isize), - tag3(isize, u8, char) + tag3(isize, u8, char), } impl cmp::PartialEq for t { fn eq(&self, other: &t) -> bool { match *self { - t::tag1 => { - match (*other) { - t::tag1 => true, - _ => false - } - } - t::tag2(e0a) => { - match (*other) { - t::tag2(e0b) => e0a == e0b, - _ => false - } - } - t::tag3(e0a, e1a, e2a) => { - match (*other) { - t::tag3(e0b, e1b, e2b) => - e0a == e0b && e1a == e1b && e2a == e2b, - _ => false - } - } + t::tag1 => match (*other) { + t::tag1 => true, + _ => false, + }, + t::tag2(e0a) => match (*other) { + t::tag2(e0b) => e0a == e0b, + _ => false, + }, + t::tag3(e0a, e1a, e2a) => match (*other) { + t::tag3(e0b, e1b, e2b) => e0a == e0b && e1a == e1b && e2a == e2b, + _ => false, + }, } } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } + fn ne(&self, other: &t) -> bool { + !(*self).eq(other) + } } fn test_tag() { diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs index 687322d4dc9..a545beee599 100644 --- a/tests/ui/threads-sendsync/task-comm-17.rs +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -9,9 +9,8 @@ use std::thread; -fn f() { -} +fn f() {} pub fn main() { - thread::spawn(move|| f() ).join(); + thread::spawn(move || f()).join(); } diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs index 26f3eaf9dc6..565d97596c7 100644 --- a/tests/ui/threads-sendsync/task-comm-3.rs +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -2,10 +2,13 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } +pub fn main() { + println!("===== WITHOUT THREADS ====="); + test00(); +} fn test00_start(ch: &Sender<isize>, message: isize, count: isize) { println!("Starting test00_start"); @@ -34,9 +37,7 @@ fn test00() { let tx = tx.clone(); results.push(thread::spawn({ let i = i; - move|| { - test00_start(&tx, i, number_of_messages) - } + move || test00_start(&tx, i, number_of_messages) })); i = i + 1; } @@ -53,7 +54,9 @@ fn test00() { } // Join spawned threads... - for r in results { r.join(); } + for r in results { + r.join(); + } println!("Completed: Final number is: "); println!("{}", sum); diff --git a/tests/ui/threads-sendsync/task-comm-4.rs b/tests/ui/threads-sendsync/task-comm-4.rs index 1210cee5582..6223f6a1ded 100644 --- a/tests/ui/threads-sendsync/task-comm-4.rs +++ b/tests/ui/threads-sendsync/task-comm-4.rs @@ -3,7 +3,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; diff --git a/tests/ui/threads-sendsync/task-comm-5.rs b/tests/ui/threads-sendsync/task-comm-5.rs index e07aa18c24d..e008b28f56c 100644 --- a/tests/ui/threads-sendsync/task-comm-5.rs +++ b/tests/ui/threads-sendsync/task-comm-5.rs @@ -2,7 +2,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let _r: isize = 0; @@ -10,8 +12,14 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 1000; let mut i: isize = 0; - while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + tx.send(i + 0).unwrap(); + i += 1; + } i = 0; - while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } + while i < number_of_messages { + sum += rx.recv().unwrap(); + i += 1; + } assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/tests/ui/threads-sendsync/task-comm-6.rs b/tests/ui/threads-sendsync/task-comm-6.rs index 6a7dea63993..60697c908af 100644 --- a/tests/ui/threads-sendsync/task-comm-6.rs +++ b/tests/ui/threads-sendsync/task-comm-6.rs @@ -4,7 +4,9 @@ use std::sync::mpsc::channel; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00() { let mut r: isize = 0; @@ -38,5 +40,4 @@ fn test00() { assert_eq!(sum, 1998000); // assert (sum == 4 * ((number_of_messages * // (number_of_messages - 1)) / 2)); - } diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs index d9b322daa66..bb59e4b4a72 100644 --- a/tests/ui/threads-sendsync/task-comm-7.rs +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -6,12 +6,16 @@ use std::sync::mpsc::{channel, Sender}; use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} -fn test00_start(c: &Sender<isize>, start: isize, - number_of_messages: isize) { +fn test00_start(c: &Sender<isize>, start: isize, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } + while i < number_of_messages { + c.send(start + i).unwrap(); + i += 1; + } } fn test00() { @@ -21,19 +25,19 @@ fn test00() { let number_of_messages: isize = 10; let tx2 = tx.clone(); - let t1 = thread::spawn(move|| { + let t1 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let t2 = thread::spawn(move|| { + let t2 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let t3 = thread::spawn(move|| { + let t3 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let t4 = thread::spawn(move|| { + let t4 = thread::spawn(move || { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs index 3e617e4a40c..2e1f3cb673a 100644 --- a/tests/ui/threads-sendsync/task-comm-9.rs +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -2,14 +2,19 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::{channel, Sender}; +use std::thread; -pub fn main() { test00(); } +pub fn main() { + test00(); +} fn test00_start(c: &Sender<isize>, number_of_messages: isize) { let mut i: isize = 0; - while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } + while i < number_of_messages { + c.send(i + 0).unwrap(); + i += 1; + } } fn test00() { @@ -18,7 +23,7 @@ fn test00() { let (tx, rx) = channel(); let number_of_messages: isize = 10; - let result = thread::spawn(move|| { + let result = thread::spawn(move || { test00_start(&tx, number_of_messages); }); diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs index d3eca5d371f..f08a281e76c 100644 --- a/tests/ui/threads-sendsync/task-life-0.rs +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -6,9 +6,7 @@ use std::thread; pub fn main() { - thread::spawn(move|| child("Hello".to_string()) ).join(); + thread::spawn(move || child("Hello".to_string())).join(); } -fn child(_s: String) { - -} +fn child(_s: String) {} diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs index ea1c6a9b108..07d1a3d5c36 100644 --- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -2,8 +2,8 @@ #![allow(unused_must_use)] //@ needs-threads -use std::thread; use std::sync::mpsc::channel; +use std::thread; pub fn main() { let (tx, rx) = channel::<usize>(); diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs index cad10c7a792..3934084e02a 100644 --- a/tests/ui/threads-sendsync/task-stderr.rs +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -4,20 +4,21 @@ #![feature(internal_output_capture)] -use std::io; -use std::str; use std::sync::{Arc, Mutex}; -use std::thread; +use std::{io, str, thread}; fn main() { let data = Arc::new(Mutex::new(Vec::new())); - let res = thread::Builder::new().spawn({ - let data = data.clone(); - move || { - io::set_output_capture(Some(data)); - panic!("Hello, world!") - } - }).unwrap().join(); + let res = thread::Builder::new() + .spawn({ + let data = data.clone(); + move || { + io::set_output_capture(Some(data)); + panic!("Hello, world!") + } + }) + .unwrap() + .join(); assert!(res.is_err()); let output = data.lock().unwrap(); diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs index 429a4657314..b2f76a55fb9 100644 --- a/tests/ui/threads-sendsync/tcp-stress.rs +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -8,14 +8,14 @@ use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::process; use std::sync::mpsc::channel; -use std::time::Duration; use std::thread::{self, Builder}; +use std::time::Duration; const TARGET_CNT: usize = 200; fn main() { // This test has a chance to time out, try to not let it time out - thread::spawn(move|| -> () { + thread::spawn(move || -> () { thread::sleep(Duration::from_secs(30)); process::exit(1); }); @@ -38,12 +38,12 @@ fn main() { let mut spawned_cnt = 0; for _ in 0..TARGET_CNT { let tx = tx.clone(); - let res = Builder::new().stack_size(64 * 1024).spawn(move|| { + let res = Builder::new().stack_size(64 * 1024).spawn(move || { match TcpStream::connect(addr) { Ok(mut stream) => { let _ = stream.write(&[1]); let _ = stream.read(&mut [0]); - }, + } Err(..) => {} } tx.send(()).unwrap(); diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs index f3ed7890364..ad4e4774ea0 100644 --- a/tests/ui/threads-sendsync/threads.rs +++ b/tests/ui/threads-sendsync/threads.rs @@ -7,10 +7,16 @@ use std::thread; pub fn main() { let mut i = 10; while i > 0 { - thread::spawn({let i = i; move|| child(i)}).join(); + thread::spawn({ + let i = i; + move || child(i) + }) + .join(); i = i - 1; } println!("main thread exiting"); } -fn child(x: isize) { println!("{}", x); } +fn child(x: isize) { + println!("{}", x); +} diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs index 84176659412..983028681cd 100644 --- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -8,7 +8,9 @@ struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { HIT = true; } + unsafe { + HIT = true; + } } } @@ -17,6 +19,8 @@ thread_local!(static FOO: Foo = Foo); fn main() { std::thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); assert!(unsafe { HIT }); } diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs index fd764669e7f..1cae19aae86 100644 --- a/tests/ui/threads-sendsync/tls-init-on-init.rs +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -1,14 +1,14 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] -use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::thread; -struct Foo { cnt: usize } +struct Foo { + cnt: usize, +} thread_local!(static FOO: Foo = Foo::init()); @@ -40,5 +40,7 @@ impl Drop for Foo { fn main() { thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); } diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs index 72cee219a0a..04071e77daa 100644 --- a/tests/ui/threads-sendsync/tls-try-with.rs +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -1,8 +1,6 @@ //@ run-pass #![allow(stable_features)] - //@ needs-threads - #![feature(thread_local_try_with)] use std::thread; @@ -16,15 +14,17 @@ thread_local!(static FOO: Foo = Foo {}); impl Drop for Foo { fn drop(&mut self) { assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); - unsafe { DROP_RUN = true; } + unsafe { + DROP_RUN = true; + } } } fn main() { thread::spawn(|| { - assert_eq!(FOO.try_with(|_| { - 132 - }).expect("`try_with` failed"), 132); - }).join().unwrap(); + assert_eq!(FOO.try_with(|_| { 132 }).expect("`try_with` failed"), 132); + }) + .join() + .unwrap(); assert!(unsafe { DROP_RUN }); } diff --git a/tests/ui/threads-sendsync/trivial-message.rs b/tests/ui/threads-sendsync/trivial-message.rs index 81657373643..d76ba0009dc 100644 --- a/tests/ui/threads-sendsync/trivial-message.rs +++ b/tests/ui/threads-sendsync/trivial-message.rs @@ -2,9 +2,9 @@ #![allow(unused_must_use)] /* - This is about the simplest program that can successfully send a - message. - */ + This is about the simplest program that can successfully send a + message. +*/ use std::sync::mpsc::channel; diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs index 3b1ab57b46e..ec27a1846fe 100644 --- a/tests/ui/threads-sendsync/unwind-resource.rs +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -21,9 +21,7 @@ impl Drop for complainer { fn complainer(tx: Sender<bool>) -> complainer { println!("Hello!"); - complainer { - tx: tx - } + complainer { tx: tx } } fn f(tx: Sender<bool>) { @@ -33,7 +31,7 @@ fn f(tx: Sender<bool>) { pub fn main() { let (tx, rx) = channel(); - let t = thread::spawn(move|| f(tx.clone())); + let t = thread::spawn(move || f(tx.clone())); println!("hiiiiiiiii"); assert!(rx.recv().unwrap()); drop(t.join()); diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs index 99d14bd92ea..c2b10b901cf 100644 --- a/tests/ui/threads-sendsync/yield.rs +++ b/tests/ui/threads-sendsync/yield.rs @@ -17,5 +17,9 @@ pub fn main() { } fn child() { - println!("4"); thread::yield_now(); println!("5"); thread::yield_now(); println!("6"); + println!("4"); + thread::yield_now(); + println!("5"); + thread::yield_now(); + println!("6"); } diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs index c965d2fc303..441e93ecf90 100644 --- a/tests/ui/threads-sendsync/yield1.rs +++ b/tests/ui/threads-sendsync/yield1.rs @@ -13,4 +13,6 @@ pub fn main() { result.join(); } -fn child() { println!("2"); } +fn child() { + println!("2"); +} diff --git a/tests/ui/threads-sendsync/yield2.rs b/tests/ui/threads-sendsync/yield2.rs index 9502f0d33da..2c24df44af2 100644 --- a/tests/ui/threads-sendsync/yield2.rs +++ b/tests/ui/threads-sendsync/yield2.rs @@ -4,5 +4,9 @@ use std::thread; pub fn main() { let mut i: isize = 0; - while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); } + while i < 100 { + i = i + 1; + println!("{}", i); + thread::yield_now(); + } } diff --git a/tests/ui/transmutability/abstraction/abstracted_assume.rs b/tests/ui/transmutability/abstraction/abstracted_assume.rs index 897e1b4b50a..7fd91e31a04 100644 --- a/tests/ui/transmutability/abstraction/abstracted_assume.rs +++ b/tests/ui/transmutability/abstraction/abstracted_assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -16,7 +16,7 @@ mod assert { const ASSUME: std::mem::Assume, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, ASSUME, >, diff --git a/tests/ui/transmutability/abstraction/const_generic_fn.rs b/tests/ui/transmutability/abstraction/const_generic_fn.rs index 0a5f0de0214..1ea978ce1ba 100644 --- a/tests/ui/transmutability/abstraction/const_generic_fn.rs +++ b/tests/ui/transmutability/abstraction/const_generic_fn.rs @@ -6,12 +6,12 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn array_like<T, E, const N: usize>() where - T: BikeshedIntrinsicFrom<[E; N], { Assume::SAFETY }>, - [E; N]: BikeshedIntrinsicFrom<T, { Assume::SAFETY }> + T: TransmuteFrom<[E; N], { Assume::SAFETY }>, + [E; N]: TransmuteFrom<T, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/alignment/align-fail.rs b/tests/ui/transmutability/alignment/align-fail.rs index d88f1285c11..4c1a69b0128 100644 --- a/tests/ui/transmutability/alignment/align-fail.rs +++ b/tests/ui/transmutability/alignment/align-fail.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: true, diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index f05e55fb024..b9801e511b2 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: false, diff --git a/tests/ui/transmutability/alignment/align-pass.rs b/tests/ui/transmutability/alignment/align-pass.rs index aecf7b02d62..feecf5edaa1 100644 --- a/tests/ui/transmutability/alignment/align-pass.rs +++ b/tests/ui/transmutability/alignment/align-pass.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, diff --git a/tests/ui/transmutability/arrays/huge-len.rs b/tests/ui/transmutability/arrays/huge-len.rs index 3fe254ebef4..dec24a559d3 100644 --- a/tests/ui/transmutability/arrays/huge-len.rs +++ b/tests/ui/transmutability/arrays/huge-len.rs @@ -1,11 +1,11 @@ #![crate_type = "lib"] #![feature(transmutability)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr index 37160c5c959..1fa16c649d4 100644 --- a/tests/ui/transmutability/arrays/huge-len.stderr +++ b/tests/ui/transmutability/arrays/huge-len.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src>, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` --> $DIR/huge-len.rs:24:55 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src>, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.rs b/tests/ui/transmutability/arrays/issue-103783-array-length.rs index 7fcbcc01075..3537a39259c 100644 --- a/tests/ui/transmutability/arrays/issue-103783-array-length.rs +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.rs @@ -3,11 +3,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/arrays/should_have_correct_length.rs b/tests/ui/transmutability/arrays/should_have_correct_length.rs index 747897d49d7..00c0c1122ef 100644 --- a/tests/ui/transmutability/arrays/should_have_correct_length.rs +++ b/tests/ui/transmutability/arrays/should_have_correct_length.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/arrays/should_inherit_alignment.rs b/tests/ui/transmutability/arrays/should_inherit_alignment.rs index d95c51e3361..70d2f07c449 100644 --- a/tests/ui/transmutability/arrays/should_inherit_alignment.rs +++ b/tests/ui/transmutability/arrays/should_inherit_alignment.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs index 5345b199f6e..29e8ad136ee 100644 --- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr index b4cd70142c4..e9420cd393e 100644 --- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -31,7 +31,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -52,7 +52,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -73,7 +73,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -94,7 +94,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) @@ -115,7 +115,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/niche_optimization.rs b/tests/ui/transmutability/enums/niche_optimization.rs index 23f57ecad75..802d1747568 100644 --- a/tests/ui/transmutability/enums/niche_optimization.rs +++ b/tests/ui/transmutability/enums/niche_optimization.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, @@ -21,7 +21,7 @@ mod assert { pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, diff --git a/tests/ui/transmutability/enums/repr/padding_differences.rs b/tests/ui/transmutability/enums/repr/padding_differences.rs index d0e1502b5e2..9d2380c613e 100644 --- a/tests/ui/transmutability/enums/repr/padding_differences.rs +++ b/tests/ui/transmutability/enums/repr/padding_differences.rs @@ -7,11 +7,11 @@ use std::mem::MaybeUninit; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, @@ -23,7 +23,7 @@ mod assert { pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: false, diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs index d3d463e7929..a8f4cccc73e 100644 --- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs @@ -5,11 +5,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr index 6c88bf4ff96..c975ff276c8 100644 --- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -32,7 +32,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -54,7 +54,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -76,7 +76,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -98,7 +98,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -120,7 +120,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -142,7 +142,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -164,7 +164,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -186,7 +186,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -208,7 +208,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -230,7 +230,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -252,7 +252,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -274,7 +274,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -296,7 +296,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -318,7 +318,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -340,7 +340,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -362,7 +362,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -384,7 +384,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -406,7 +406,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -428,7 +428,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/enums/repr/should_handle_all.rs b/tests/ui/transmutability/enums/repr/should_handle_all.rs index a8ec86fa40d..dec0126f22d 100644 --- a/tests/ui/transmutability/enums/repr/should_handle_all.rs +++ b/tests/ui/transmutability/enums/repr/should_handle_all.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/enums/should_order_correctly.rs b/tests/ui/transmutability/enums/should_order_correctly.rs index d51a033f1a6..cea2055e148 100644 --- a/tests/ui/transmutability/enums/should_order_correctly.rs +++ b/tests/ui/transmutability/enums/should_order_correctly.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_pad_variants.rs b/tests/ui/transmutability/enums/should_pad_variants.rs index 81ef9e8a567..82bafe85415 100644 --- a/tests/ui/transmutability/enums/should_pad_variants.rs +++ b/tests/ui/transmutability/enums/should_pad_variants.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr index da4294bdbce..bb26281c2f0 100644 --- a/tests/ui/transmutability/enums/should_pad_variants.stderr +++ b/tests/ui/transmutability/enums/should_pad_variants.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/should_respect_endianness.rs b/tests/ui/transmutability/enums/should_respect_endianness.rs index 8e52274710a..9cf4de06ad2 100644 --- a/tests/ui/transmutability/enums/should_respect_endianness.rs +++ b/tests/ui/transmutability/enums/should_respect_endianness.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr index 9f88bb06813..1b9099b297b 100644 --- a/tests/ui/transmutability/enums/should_respect_endianness.stderr +++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/enums/uninhabited_optimization.rs b/tests/ui/transmutability/enums/uninhabited_optimization.rs index c2d5b67ab2c..5b9de3a3963 100644 --- a/tests/ui/transmutability/enums/uninhabited_optimization.rs +++ b/tests/ui/transmutability/enums/uninhabited_optimization.rs @@ -4,7 +4,7 @@ fn assert_transmutable<T>() where - (): std::mem::BikeshedIntrinsicFrom<T> + (): std::mem::TransmuteFrom<T> {} enum Uninhabited {} diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index 81a9038fdb5..fcc1db073ee 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -1,11 +1,11 @@ #![feature(transmutability)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, const ASSUME_ALIGNMENT: bool>() where - Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope + Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope //~| the constant `ASSUME_ALIGNMENT` is not of type `Assume` //~| ERROR: mismatched types { diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index 6f79bf7b424..3687631dc51 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -1,23 +1,23 @@ error[E0412]: cannot find type `Dst` in this scope --> $DIR/issue-101739-1.rs:8:9 | -LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, | ^^^ not found in this scope error: the constant `ASSUME_ALIGNMENT` is not of type `Assume` --> $DIR/issue-101739-1.rs:8:14 | -LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` | -note: required by a const generic parameter in `BikeshedIntrinsicFrom` +note: required by a const generic parameter in `TransmuteFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL error[E0308]: mismatched types - --> $DIR/issue-101739-1.rs:8:41 + --> $DIR/issue-101739-1.rs:8:33 | -LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, - | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` +LL | Dst: TransmuteFrom<Src, ASSUME_ALIGNMENT>, + | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` error: aborting due to 3 previous errors diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs index 6dfde06d6b3..02aa4669e05 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable< Src, @@ -14,7 +14,7 @@ mod assert { const ASSUME_VISIBILITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< //~^ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied Src, ASSUME_ALIGNMENT, //~ ERROR: mismatched types diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 11e8fa1d8c5..526fcabe14e 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -1,8 +1,8 @@ error[E0107]: trait takes at most 2 generic arguments but 5 generic arguments were supplied --> $DIR/issue-101739-2.rs:17:14 | -LL | Dst: BikeshedIntrinsicFrom< - | ^^^^^^^^^^^^^^^^^^^^^ expected at most 2 generic arguments +LL | Dst: TransmuteFrom< + | ^^^^^^^^^^^^^ expected at most 2 generic arguments ... LL | ASSUME_ALIGNMENT, | _________________________________- diff --git a/tests/ui/transmutability/issue-110467.rs b/tests/ui/transmutability/issue-110467.rs index 1f9e521c24b..4acea5f766d 100644 --- a/tests/ui/transmutability/issue-110467.rs +++ b/tests/ui/transmutability/issue-110467.rs @@ -1,11 +1,11 @@ //@ check-pass #![crate_type = "lib"] #![feature(transmutability)] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } diff --git a/tests/ui/transmutability/issue-110892.rs b/tests/ui/transmutability/issue-110892.rs index 9713684c959..ad1b9e7af10 100644 --- a/tests/ui/transmutability/issue-110892.rs +++ b/tests/ui/transmutability/issue-110892.rs @@ -3,7 +3,7 @@ #![allow(incomplete_features)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -14,7 +14,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs index 30c381745d0..07133aa5614 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -2,7 +2,7 @@ #![crate_type = "lib"] -use std::mem::BikeshedIntrinsicFrom; +use std::mem::TransmuteFrom; //~^ ERROR use of unstable library feature 'transmutability' [E0658] use std::mem::Assume; diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr index 9f221907172..a2096cd53e5 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature 'transmutability' --> $DIR/feature-missing.rs:5:5 | -LL | use std::mem::BikeshedIntrinsicFrom; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use std::mem::TransmuteFrom; + | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information = help: add `#![feature(transmutability)]` to the crate attributes to enable diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs index bcfbc1430a8..b8828c59d35 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs index 8c18de11196..2285d2f532e 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs @@ -5,11 +5,11 @@ #![allow(incomplete_features)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr index df10919f6d3..564aee687a5 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.stderr @@ -22,8 +22,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `should_gracefully_handle_unknown_dst_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_dst_ref_field::Dst` --> $DIR/unknown_dst_field.rs:25:36 @@ -37,8 +37,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 4 previous errors diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs index bd7c3fc7fb5..10ba7a61b87 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs index 1da16e67223..598e04971e2 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr index 6ec66e17061..1156391c301 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -22,8 +22,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `should_gracefully_handle_unknown_src_ref_field::Src` cannot be safely transmuted into `should_gracefully_handle_unknown_src_ref_field::Dst` --> $DIR/unknown_src_field.rs:25:36 @@ -37,8 +37,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 4 previous errors diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs index 608366fa089..df925975bad 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -8,7 +8,7 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable< Src, @@ -19,7 +19,7 @@ mod assert { const ASSUME_VALIDITY: bool, >() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } >, diff --git a/tests/ui/transmutability/maybeuninit.rs b/tests/ui/transmutability/maybeuninit.rs index 77c3381c774..7b60785b7e0 100644 --- a/tests/ui/transmutability/maybeuninit.rs +++ b/tests/ui/transmutability/maybeuninit.rs @@ -5,11 +5,11 @@ use std::mem::MaybeUninit; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/maybeuninit.stderr b/tests/ui/transmutability/maybeuninit.stderr index be7dcaf35ea..897c2df10a8 100644 --- a/tests/ui/transmutability/maybeuninit.stderr +++ b/tests/ui/transmutability/maybeuninit.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool-mut.rs b/tests/ui/transmutability/primitives/bool-mut.rs index 09b6d582d87..0a7dad37aaf 100644 --- a/tests/ui/transmutability/primitives/bool-mut.rs +++ b/tests/ui/transmutability/primitives/bool-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr index a6cf146659e..fcf60bc979c 100644 --- a/tests/ui/transmutability/primitives/bool-mut.stderr +++ b/tests/ui/transmutability/primitives/bool-mut.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.current.stderr +++ b/tests/ui/transmutability/primitives/bool.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr index da6a4a44e95..2945cdaad40 100644 --- a/tests/ui/transmutability/primitives/bool.next.stderr +++ b/tests/ui/transmutability/primitives/bool.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs index 19236a1ae2e..6fac8ba1ad1 100644 --- a/tests/ui/transmutability/primitives/bool.rs +++ b/tests/ui/transmutability/primitives/bool.rs @@ -4,16 +4,16 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index 0a9b9d182f8..efb2ce8c772 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:65:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:66:40 @@ -40,8 +40,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:67:40 @@ -55,8 +55,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:68:40 @@ -70,8 +70,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:69:40 @@ -85,8 +85,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:70:40 @@ -100,8 +100,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:71:40 @@ -115,8 +115,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:72:39 @@ -130,8 +130,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:73:39 @@ -145,8 +145,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` --> $DIR/numbers.rs:75:40 @@ -160,8 +160,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` --> $DIR/numbers.rs:76:40 @@ -175,8 +175,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:77:40 @@ -190,8 +190,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:78:40 @@ -205,8 +205,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:79:40 @@ -220,8 +220,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:80:40 @@ -235,8 +235,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:81:40 @@ -250,8 +250,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:82:40 @@ -265,8 +265,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:83:39 @@ -280,8 +280,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:84:39 @@ -295,8 +295,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:86:40 @@ -310,8 +310,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:87:40 @@ -325,8 +325,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:88:40 @@ -340,8 +340,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:89:40 @@ -355,8 +355,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:90:40 @@ -370,8 +370,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:91:40 @@ -385,8 +385,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:92:39 @@ -400,8 +400,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:93:39 @@ -415,8 +415,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` --> $DIR/numbers.rs:95:40 @@ -430,8 +430,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` --> $DIR/numbers.rs:96:40 @@ -445,8 +445,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` --> $DIR/numbers.rs:97:40 @@ -460,8 +460,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:98:40 @@ -475,8 +475,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:99:40 @@ -490,8 +490,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:100:40 @@ -505,8 +505,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:101:39 @@ -520,8 +520,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:102:39 @@ -535,8 +535,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:104:40 @@ -550,8 +550,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:105:40 @@ -565,8 +565,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:106:40 @@ -580,8 +580,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:107:39 @@ -595,8 +595,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:108:39 @@ -610,8 +610,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:110:40 @@ -625,8 +625,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:111:40 @@ -640,8 +640,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:112:40 @@ -655,8 +655,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:113:39 @@ -670,8 +670,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:114:39 @@ -685,8 +685,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` --> $DIR/numbers.rs:116:40 @@ -700,8 +700,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` --> $DIR/numbers.rs:117:40 @@ -715,8 +715,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` --> $DIR/numbers.rs:118:40 @@ -730,8 +730,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:119:39 @@ -745,8 +745,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:120:39 @@ -760,8 +760,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:122:39 @@ -775,8 +775,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:123:39 @@ -790,8 +790,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:125:39 @@ -805,8 +805,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:126:39 @@ -820,8 +820,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` --> $DIR/numbers.rs:128:39 @@ -835,8 +835,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` --> $DIR/numbers.rs:129:39 @@ -850,8 +850,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 57 previous errors diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs index 401502474cf..b5c21c992b6 100644 --- a/tests/ui/transmutability/primitives/numbers.rs +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -7,11 +7,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> + Dst: TransmuteFrom<Src> {} } diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr index 52b708d680e..4bfb229832b 100644 --- a/tests/ui/transmutability/primitives/unit.current.stderr +++ b/tests/ui/transmutability/primitives/unit.current.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/primitives/unit.next.stderr b/tests/ui/transmutability/primitives/unit.next.stderr index 52b708d680e..4bfb229832b 100644 --- a/tests/ui/transmutability/primitives/unit.next.stderr +++ b/tests/ui/transmutability/primitives/unit.next.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs index 44216950f55..93b21e0b586 100644 --- a/tests/ui/transmutability/primitives/unit.rs +++ b/tests/ui/transmutability/primitives/unit.rs @@ -9,11 +9,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs b/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs index 3bdd7256791..edad02fc96d 100644 --- a/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs +++ b/tests/ui/transmutability/references/accept_assume_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::LIFETIMES) }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::LIFETIMES) }>, { core::intrinsics::transmute_unchecked(src) } @@ -82,7 +82,7 @@ mod hrtb { unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 where - for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8, { Assume::LIFETIMES }>, + for<'b> &'b u8: TransmuteFrom<&'a u8, { Assume::LIFETIMES }>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs index 559ee23a446..5734575e90b 100644 --- a/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs +++ b/tests/ui/transmutability/references/accept_unexercised_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY }>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs index ba2db755e3b..92068ee0d4f 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr index 4b2866dc4f0..1698021d554 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible-mut.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs index cd70c278285..8e2da3518a9 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs index 2f264e8339e..01b176cc3c1 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr index 2b7cab1660d..dbd3e39b365 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr +++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-incompatible.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.rs b/tests/ui/transmutability/references/recursive-wrapper-types.rs index 28f4d6661cb..53dedeb6388 100644 --- a/tests/ui/transmutability/references/recursive-wrapper-types.rs +++ b/tests/ui/transmutability/references/recursive-wrapper-types.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/reject_extension.rs b/tests/ui/transmutability/references/reject_extension.rs index 161da5772e8..dd02e5c01c4 100644 --- a/tests/ui/transmutability/references/reject_extension.rs +++ b/tests/ui/transmutability/references/reject_extension.rs @@ -6,11 +6,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { diff --git a/tests/ui/transmutability/references/reject_extension.stderr b/tests/ui/transmutability/references/reject_extension.stderr index 88dd0313e3c..182106acf12 100644 --- a/tests/ui/transmutability/references/reject_extension.stderr +++ b/tests/ui/transmutability/references/reject_extension.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom< +LL | Dst: TransmuteFrom< | ______________^ LL | | Src, LL | | { diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.rs b/tests/ui/transmutability/references/reject_lifetime_extension.rs index 79bb4e1e556..ff9290c34af 100644 --- a/tests/ui/transmutability/references/reject_lifetime_extension.rs +++ b/tests/ui/transmutability/references/reject_lifetime_extension.rs @@ -4,11 +4,11 @@ #![feature(transmutability, core_intrinsics)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; unsafe fn transmute<Src, Dst>(src: Src) -> Dst where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }>, + Dst: TransmuteFrom<Src, { Assume::SAFETY }>, { core::intrinsics::transmute_unchecked(src) } @@ -82,7 +82,7 @@ mod hrtb { unsafe fn extend_hrtb<'a>(src: &'a u8) -> &'static u8 where - for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8>, + for<'b> &'b u8: TransmuteFrom<&'a u8>, { core::intrinsics::transmute_unchecked(src) } diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.stderr b/tests/ui/transmutability/references/reject_lifetime_extension.stderr index df1b81f26d2..a597041c6ca 100644 --- a/tests/ui/transmutability/references/reject_lifetime_extension.stderr +++ b/tests/ui/transmutability/references/reject_lifetime_extension.stderr @@ -70,8 +70,8 @@ LL | unsafe { extend_hrtb(src) } note: due to current limitations in the borrow checker, this implies a `'static` lifetime --> $DIR/reject_lifetime_extension.rs:85:25 | -LL | for<'b> &'b u8: BikeshedIntrinsicFrom<&'a u8>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | for<'b> &'b u8: TransmuteFrom<&'a u8>, + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/transmutability/references/u8-to-unit.rs b/tests/ui/transmutability/references/u8-to-unit.rs index 017b73d9595..98deb6457cb 100644 --- a/tests/ui/transmutability/references/u8-to-unit.rs +++ b/tests/ui/transmutability/references/u8-to-unit.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: false, lifetimes: true, diff --git a/tests/ui/transmutability/references/unit-to-itself.rs b/tests/ui/transmutability/references/unit-to-itself.rs index 40aec8418fe..789455c03ea 100644 --- a/tests/ui/transmutability/references/unit-to-itself.rs +++ b/tests/ui/transmutability/references/unit-to-itself.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: false, diff --git a/tests/ui/transmutability/references/unit-to-u8.rs b/tests/ui/transmutability/references/unit-to-u8.rs index 973d3206c12..575a40e3622 100644 --- a/tests/ui/transmutability/references/unit-to-u8.rs +++ b/tests/ui/transmutability/references/unit-to-u8.rs @@ -2,11 +2,11 @@ #![feature(transmutability)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index 5d73dfdc8eb..b5a79b1917f 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/references/unsafecell.rs b/tests/ui/transmutability/references/unsafecell.rs index a8a1f969fb4..4001f139770 100644 --- a/tests/ui/transmutability/references/unsafecell.rs +++ b/tests/ui/transmutability/references/unsafecell.rs @@ -5,11 +5,11 @@ use std::cell::UnsafeCell; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/references/unsafecell.stderr b/tests/ui/transmutability/references/unsafecell.stderr index 8bb32359355..6664d8a7d6f 100644 --- a/tests/ui/transmutability/references/unsafecell.stderr +++ b/tests/ui/transmutability/references/unsafecell.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8>` --> $DIR/unsafecell.rs:29:62 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/region-infer.rs b/tests/ui/transmutability/region-infer.rs index 0632bc53176..c164f35c447 100644 --- a/tests/ui/transmutability/region-infer.rs +++ b/tests/ui/transmutability/region-infer.rs @@ -1,13 +1,13 @@ #![feature(transmutability)] -use std::mem::{Assume, BikeshedIntrinsicFrom}; +use std::mem::{Assume, TransmuteFrom}; #[repr(C)] struct W<'a>(&'a ()); fn test<'a>() where - W<'a>: BikeshedIntrinsicFrom< + W<'a>: TransmuteFrom< (), { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 03c46823838..09ecf484bc8 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -10,7 +10,7 @@ note: required by a bound in `test` LL | fn test<'a>() | ---- required by a bound in this function LL | where -LL | W<'a>: BikeshedIntrinsicFrom< +LL | W<'a>: TransmuteFrom< | ____________^ LL | | (), LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs index cb3c1cdf46c..0113049f51e 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_dst_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs index b12c4a10d12..eca7a06559d 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_ref_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs index ff01462ffec..46e84b48044 100644 --- a/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/assume/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs index d516e9a7da5..aaba6febde4 100644 --- a/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_accept_if_src_has_safety_invariant.rs @@ -8,11 +8,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs index 4f0aee31548..6f8e383db1f 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr index 2339c268326..6445b1e146e 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs index 126059dd7b7..16d163d5420 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::BikeshedIntrinsicFrom; + use std::mem::TransmuteFrom; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed + Dst: TransmuteFrom<Src> // safety is NOT assumed {} } diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr index 99feebe9211..38ef829f064 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src> // safety is NOT assumed - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/structs/repr/should_handle_align.rs b/tests/ui/transmutability/structs/repr/should_handle_align.rs index 0c207766045..03065298b50 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_align.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/should_handle_all.rs b/tests/ui/transmutability/structs/repr/should_handle_all.rs index 52c24eecf12..e5ca37e68ec 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_all.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_all.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/should_handle_packed.rs b/tests/ui/transmutability/structs/repr/should_handle_packed.rs index 4af32d6e84e..c9be32d7b2a 100644 --- a/tests/ui/transmutability/structs/repr/should_handle_packed.rs +++ b/tests/ui/transmutability/structs/repr/should_handle_packed.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs index 4c285a616b3..8d291054365 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs @@ -7,11 +7,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src>, + Dst: TransmuteFrom<Src>, { } } diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr index 7fb051f6625..bdf2d3b6a58 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr @@ -12,7 +12,7 @@ LL | struct ExplicitlyPadded(Box<ExplicitlyPadded>); error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` | = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again - = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::BikeshedIntrinsicFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, core::mem::transmutability::Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` + = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, core::mem::transmutability::Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/structs/should_order_fields_correctly.rs b/tests/ui/transmutability/structs/should_order_fields_correctly.rs index 3675e4330ec..aa9ca39eff2 100644 --- a/tests/ui/transmutability/structs/should_order_fields_correctly.rs +++ b/tests/ui/transmutability/structs/should_order_fields_correctly.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/transmute-padding-ice.rs b/tests/ui/transmutability/transmute-padding-ice.rs index f5935a0009e..133241c89cb 100644 --- a/tests/ui/transmutability/transmute-padding-ice.rs +++ b/tests/ui/transmutability/transmute-padding-ice.rs @@ -9,11 +9,11 @@ use std::mem::size_of; mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom< + Dst: TransmuteFrom< Src, { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, >, diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs index 7524922c16a..74f7a1a2e89 100644 --- a/tests/ui/transmutability/uninhabited.rs +++ b/tests/ui/transmutability/uninhabited.rs @@ -3,11 +3,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 88a98c798fc..3fa02f0867c 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -34,7 +34,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -56,7 +56,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -78,7 +78,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, @@ -100,7 +100,7 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume { LL | | alignment: true, diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs index c829f83149e..838643defd5 100644 --- a/tests/ui/transmutability/unions/boolish.rs +++ b/tests/ui/transmutability/unions/boolish.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/unions/repr/should_handle_align.rs b/tests/ui/transmutability/unions/repr/should_handle_align.rs index ba4e904e161..0605651bd7b 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_align.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_align.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/repr/should_handle_all.rs b/tests/ui/transmutability/unions/repr/should_handle_all.rs index 85d48dd9b7f..8505c7f9123 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_all.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_all.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/repr/should_handle_packed.rs b/tests/ui/transmutability/unions/repr/should_handle_packed.rs index fc06eba4353..5e9851ab0c9 100644 --- a/tests/ui/transmutability/unions/repr/should_handle_packed.rs +++ b/tests/ui/transmutability/unions/repr/should_handle_packed.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume { alignment: true, lifetimes: true, diff --git a/tests/ui/transmutability/unions/should_pad_variants.rs b/tests/ui/transmutability/unions/should_pad_variants.rs index 1e4d2db8f74..986c7fafb85 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.rs +++ b/tests/ui/transmutability/unions/should_pad_variants.rs @@ -6,11 +6,11 @@ #![allow(dead_code)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { + Dst: TransmuteFrom<Src, { Assume::ALIGNMENT .and(Assume::LIFETIMES) .and(Assume::SAFETY) diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr index da4294bdbce..bb26281c2f0 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.stderr +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -10,7 +10,7 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { +LL | Dst: TransmuteFrom<Src, { | ______________^ LL | | Assume::ALIGNMENT LL | | .and(Assume::LIFETIMES) diff --git a/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs index 7efe9ac70f1..359ba515439 100644 --- a/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs +++ b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs @@ -7,11 +7,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.rs b/tests/ui/transmutability/unions/should_reject_contraction.rs index 62a0ee92919..87398328fc7 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.rs +++ b/tests/ui/transmutability/unions/should_reject_contraction.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr index 20eaa3a6b09..ea68de14efc 100644 --- a/tests/ui/transmutability/unions/should_reject_contraction.stderr +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 1 previous error diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.rs b/tests/ui/transmutability/unions/should_reject_disjoint.rs index 732f92e8160..0427e3c44a2 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.rs +++ b/tests/ui/transmutability/unions/should_reject_disjoint.rs @@ -5,11 +5,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_maybe_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> {} } diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr index ea47797c970..d55abbe0817 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.stderr +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_disjoint.rs:33:40 @@ -25,8 +25,8 @@ note: required by a bound in `is_maybe_transmutable` LL | pub fn is_maybe_transmutable<Src, Dst>() | --------------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.rs b/tests/ui/transmutability/unions/should_reject_intersecting.rs index 752a606c861..9b3b18919f5 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.rs +++ b/tests/ui/transmutability/unions/should_reject_intersecting.rs @@ -6,11 +6,11 @@ #![allow(dead_code, incomplete_features, non_camel_case_types)] mod assert { - use std::mem::{Assume, BikeshedIntrinsicFrom}; + use std::mem::{Assume, TransmuteFrom}; pub fn is_transmutable<Src, Dst>() where - Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> + Dst: TransmuteFrom<Src, { Assume::SAFETY }> // validity is NOT assumed -----^^^^^^^^^^^^^^^^^^ {} } diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr index 79dec659d9d..522681d7d15 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.stderr +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -10,8 +10,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `B` cannot be safely transmuted into `A` --> $DIR/should_reject_intersecting.rs:36:34 @@ -25,8 +25,8 @@ note: required by a bound in `is_transmutable` LL | pub fn is_transmutable<Src, Dst>() | --------------- required by a bound in this function LL | where -LL | Dst: BikeshedIntrinsicFrom<Src, { Assume::SAFETY }> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` +LL | Dst: TransmuteFrom<Src, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error: aborting due to 2 previous errors |
