diff options
| author | bors <bors@rust-lang.org> | 2023-09-03 07:35:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-03 07:35:33 +0000 |
| commit | f2568c8316805749fe616e3de08c3f7c2bec3680 (patch) | |
| tree | 62acd3e15506a4b53b29a70b7882c0c2fa0352b4 /src | |
| parent | d2f5dc9745defa7cb90a88dd8adc7d347f42d0bc (diff) | |
| parent | fb26c21c356075c0cd35d98fa0b786b7633249d8 (diff) | |
Auto merge of #3050 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/llvm.rs | 9 | ||||
| -rw-r--r-- | src/bootstrap/sanity.rs | 23 | ||||
| -rw-r--r-- | src/doc/rustc/src/platform-support.md | 12 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 27 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 7 | ||||
| -rw-r--r-- | src/librustdoc/clean/utils.rs | 101 | ||||
| -rw-r--r-- | src/librustdoc/html/render/search_index.rs | 257 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 120 | ||||
| -rw-r--r-- | src/librustdoc/json/conversions.rs | 4 | ||||
| -rw-r--r-- | src/tools/build_helper/src/git.rs | 38 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs | 49 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/arithmetic_side_effects.rs | 30 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/arithmetic_side_effects.stderr | 14 | ||||
| -rw-r--r-- | src/tools/miri/rust-version | 2 | ||||
| -rw-r--r-- | src/tools/miri/src/lib.rs | 1 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/os_str.rs | 4 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/unix/fs.rs | 4 | ||||
| -rw-r--r-- | src/tools/miri/tests/utils/fs.rs | 2 |
18 files changed, 409 insertions, 295 deletions
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index c841cb34036..07502e0e9dd 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -24,6 +24,7 @@ use crate::util::{self, exe, output, t, up_to_date}; use crate::{CLang, GitRepo, Kind}; use build_helper::ci::CiEnv; +use build_helper::git::get_git_merge_base; #[derive(Clone)] pub struct LlvmResult { @@ -128,13 +129,19 @@ pub fn prebuilt_llvm_config( /// This retrieves the LLVM sha we *want* to use, according to git history. pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { let llvm_sha = if is_git { + // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we + // walk back further to the last bors merge commit that actually changed LLVM. The first + // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` + // in that case. + let closest_upstream = + get_git_merge_base(Some(&config.src)).unwrap_or_else(|_| "HEAD".into()); let mut rev_list = config.git(); rev_list.args(&[ PathBuf::from("rev-list"), format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(), "-n1".into(), "--first-parent".into(), - "HEAD".into(), + closest_upstream.into(), "--".into(), config.src.join("src/llvm-project"), config.src.join("src/bootstrap/download-ci-llvm-stamp"), diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 7e83b508e94..144e2acd09e 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -62,6 +62,9 @@ impl Finder { } pub fn check(build: &mut Build) { + let skip_target_sanity = + env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true"); + let path = env::var_os("PATH").unwrap_or_default(); // On Windows, quotes are invalid characters for filename paths, and if // one is present as part of the PATH then that can lead to the system @@ -166,7 +169,7 @@ than building it. // FIXME: it would be better to refactor this code to split necessary setup from pure sanity // checks, and have a regular flag for skipping the latter. Also see // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>. - if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { + if skip_target_sanity { continue; } @@ -205,7 +208,15 @@ than building it. } } - // Make sure musl-root is valid + // Some environments don't want or need these tools, such as when testing Miri. + // FIXME: it would be better to refactor this code to split necessary setup from pure sanity + // checks, and have a regular flag for skipping the latter. Also see + // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>. + if skip_target_sanity { + continue; + } + + // Make sure musl-root is valid. if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up @@ -227,14 +238,6 @@ than building it. } } - // Some environments don't want or need these tools, such as when testing Miri. - // FIXME: it would be better to refactor this code to split necessary setup from pure sanity - // checks, and have a regular flag for skipping the latter. Also see - // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>. - if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() { - continue; - } - if need_cmake && target.contains("msvc") { // There are three builds of cmake on windows: MSVC, MinGW, and // Cygwin. The Cygwin build does not have generators for Visual diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c1614d02f34..2cb0a8f3c17 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -63,8 +63,9 @@ Tools](#tier-1-with-host-tools). ## Tier 2 with Host Tools Tier 2 targets can be thought of as "guaranteed to build". The Rust project -builds official binary releases for each tier 2 target, and automated builds -ensure that each tier 2 target builds after each change. Automated tests are +builds official binary releases of the standard library (or, in some cases, +only the `core` library) for each tier 2 target, and automated builds +ensure that each tier 2 target can be used as build target after each change. Automated tests are not always run so it's not guaranteed to produce a working build, but tier 2 targets often work to quite a good degree and patches are always welcome! @@ -103,11 +104,12 @@ target | notes `x86_64-unknown-linux-musl` | 64-bit Linux with MUSL [`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64 -## Tier 2 +## Tier 2 without Host Tools Tier 2 targets can be thought of as "guaranteed to build". The Rust project -builds official binary releases for each tier 2 target, and automated builds -ensure that each tier 2 target builds after each change. Automated tests are +builds official binary releases of the standard library (or, in some cases, +only the `core` library) for each tier 2 target, and automated builds +ensure that each tier 2 target can be used as build target after each change. Automated tests are not always run so it's not guaranteed to produce a working build, but tier 2 targets often work to quite a good degree and patches are always welcome! For the full requirements, see [Tier 2 target diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e85284371d..b584c32a4c7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1959,31 +1959,44 @@ fn can_elide_trait_object_lifetime_bound<'tcx>( #[derive(Debug)] pub(crate) enum ContainerTy<'tcx> { Ref(ty::Region<'tcx>), - Regular { ty: DefId, args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, arg: usize }, + Regular { + ty: DefId, + args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, + has_self: bool, + arg: usize, + }, } impl<'tcx> ContainerTy<'tcx> { fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> { match self { Self::Ref(region) => ObjectLifetimeDefault::Arg(region), - Self::Regular { ty: container, args, arg: index } => { + Self::Regular { ty: container, args, has_self, arg: index } => { let (DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias { .. } - | DefKind::Trait - | DefKind::AssocTy - | DefKind::Variant) = tcx.def_kind(container) + | DefKind::Trait) = tcx.def_kind(container) else { return ObjectLifetimeDefault::Empty; }; let generics = tcx.generics_of(container); - let param = generics.params[index].def_id; - let default = tcx.object_lifetime_default(param); + debug_assert_eq!(generics.parent_count, 0); + + // If the container is a trait object type, the arguments won't contain the self type but the + // generics of the corresponding trait will. In such a case, offset the index by one. + // For comparison, if the container is a trait inside a bound, the arguments do contain the + // self type. + let offset = + if !has_self && generics.parent.is_none() && generics.has_self { 1 } else { 0 }; + let param = generics.params[index + offset].def_id; + let default = tcx.object_lifetime_default(param); match default { rbv::ObjectLifetimeDefault::Param(lifetime) => { + // The index is relative to the parent generics but since we don't have any, + // we don't need to translate it. let index = generics.param_def_id_to_index[&lifetime]; let arg = args.skip_binder()[index as usize].expect_region(); ObjectLifetimeDefault::Arg(arg) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9cf3c068b60..9134d5268da 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; use rustc_index::IndexVec; +use rustc_metadata::rendered_const; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_resolve::rustdoc::{add_doc_fragment, attrs_to_doc_fragments, inner_docs, DocFragment}; @@ -35,7 +36,7 @@ use rustc_target::spec::abi::Abi; use crate::clean::cfg::Cfg; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; -use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; +use crate::clean::utils::{is_literal_expr, print_evaluated_const}; use crate::core::DocContext; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -2086,7 +2087,7 @@ impl Discriminant { /// Will be `None` in the case of cross-crate reexports, and may be /// simplified pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option<String> { - self.expr.map(|body| print_const_expr(tcx, body)) + self.expr.map(|body| rendered_const(tcx, body)) } /// Will always be a machine readable number, without underscores or suffixes. pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> String { @@ -2326,7 +2327,7 @@ impl ConstantKind { ConstantKind::TyConst { ref expr } => expr.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { - print_const_expr(tcx, body) + rendered_const(tcx, body) } } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 80a7a33d2bd..7696ea0f449 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -14,6 +14,7 @@ use rustc_ast::tokenstream::TokenTree; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_metadata::rendered_const; use rustc_middle::mir; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt}; @@ -77,9 +78,10 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { pub(crate) fn ty_args_to_args<'tcx>( cx: &mut DocContext<'tcx>, args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, - mut skip_first: bool, + has_self: bool, container: Option<DefId>, ) -> Vec<GenericArg> { + let mut skip_first = has_self; let mut ret_val = Vec::with_capacity(args.skip_binder().len().saturating_sub(if skip_first { 1 } else { 0 })); @@ -99,6 +101,7 @@ pub(crate) fn ty_args_to_args<'tcx>( container.map(|container| crate::clean::ContainerTy::Regular { ty: container, args, + has_self, arg: index, }), ))), @@ -253,7 +256,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() { - print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def)) + rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def)) } else { inline::print_inlined_const(cx.tcx, def) }; @@ -365,100 +368,6 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { false } -/// Build a textual representation of an unevaluated constant expression. -/// -/// If the const expression is too complex, an underscore `_` is returned. -/// For const arguments, it's `{ _ }` to be precise. -/// This means that the output is not necessarily valid Rust code. -/// -/// Currently, only -/// -/// * literals (optionally with a leading `-`) -/// * unit `()` -/// * blocks (`{ … }`) around simple expressions and -/// * paths without arguments -/// -/// are considered simple enough. Simple blocks are included since they are -/// necessary to disambiguate unit from the unit type. -/// This list might get extended in the future. -/// -/// Without this censoring, in a lot of cases the output would get too large -/// and verbose. Consider `match` expressions, blocks and deeply nested ADTs. -/// Further, private and `doc(hidden)` fields of structs would get leaked -/// since HIR datatypes like the `body` parameter do not contain enough -/// semantic information for this function to be able to hide them – -/// at least not without significant performance overhead. -/// -/// Whenever possible, prefer to evaluate the constant first and try to -/// use a different method for pretty-printing. Ideally this function -/// should only ever be used as a fallback. -pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { - let hir = tcx.hir(); - let value = &hir.body(body).value; - - #[derive(PartialEq, Eq)] - enum Classification { - Literal, - Simple, - Complex, - } - - use Classification::*; - - fn classify(expr: &hir::Expr<'_>) -> Classification { - match &expr.kind { - hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { - if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex } - } - hir::ExprKind::Lit(_) => Literal, - hir::ExprKind::Tup([]) => Simple, - hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => { - if classify(expr) == Complex { Complex } else { Simple } - } - // Paths with a self-type or arguments are too “complex” following our measure since - // they may leak private fields of structs (with feature `adt_const_params`). - // Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`. - // Paths without arguments are definitely harmless though. - hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => { - if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex } - } - // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty - // contains const arguments. Is there a *concise* way to check for this? - hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple, - // FIXME: Can they contain const arguments and thus leak private struct fields? - hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple, - _ => Complex, - } - } - - let classification = classify(value); - - if classification == Literal - && !value.span.from_expansion() - && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) { - // For literals, we avoid invoking the pretty-printer and use the source snippet instead to - // preserve certain stylistic choices the user likely made for the sake legibility like - // - // * hexadecimal notation - // * underscores - // * character escapes - // - // FIXME: This passes through `-/*spacer*/0` verbatim. - snippet - } else if classification == Simple { - // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and - // other formatting artifacts. - rustc_hir_pretty::id_to_string(&hir, body.hir_id) - } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { - // FIXME: Omit the curly braces if the enclosing expression is an array literal - // with a repeated element (an `ExprKind::Repeat`) as in such case it - // would not actually need any disambiguation. - "{ _ }".to_owned() - } else { - "_".to_owned() - } -} - /// Given a type Path, resolve it to a Type using the TyCtxt pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { debug!("resolve_type({path:?})"); diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f34be120d29..145c7d18dd0 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1,10 +1,10 @@ use std::collections::hash_map::Entry; use std::collections::BTreeMap; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; -use serde::ser::{Serialize, SerializeStruct, Serializer}; +use serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer}; use crate::clean; use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate}; @@ -78,9 +78,9 @@ pub(crate) fn build_index<'tcx>( map: &mut FxHashMap<F, usize>, itemid: F, lastpathid: &mut usize, - crate_paths: &mut Vec<(ItemType, Symbol)>, + crate_paths: &mut Vec<(ItemType, Vec<Symbol>)>, item_type: ItemType, - path: Symbol, + path: &[Symbol], ) { match map.entry(itemid) { Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())), @@ -88,7 +88,7 @@ pub(crate) fn build_index<'tcx>( let pathid = *lastpathid; entry.insert(pathid); *lastpathid += 1; - crate_paths.push((item_type, path)); + crate_paths.push((item_type, path.to_vec())); ty.id = Some(RenderTypeId::Index(pathid)); } } @@ -100,7 +100,7 @@ pub(crate) fn build_index<'tcx>( itemid_to_pathid: &mut FxHashMap<ItemId, usize>, primitives: &mut FxHashMap<Symbol, usize>, lastpathid: &mut usize, - crate_paths: &mut Vec<(ItemType, Symbol)>, + crate_paths: &mut Vec<(ItemType, Vec<Symbol>)>, ) { if let Some(generics) = &mut ty.generics { for item in generics { @@ -131,7 +131,7 @@ pub(crate) fn build_index<'tcx>( lastpathid, crate_paths, item_type, - *fqp.last().unwrap(), + fqp, ); } else { ty.id = None; @@ -146,7 +146,7 @@ pub(crate) fn build_index<'tcx>( lastpathid, crate_paths, ItemType::Primitive, - sym, + &[sym], ); } RenderTypeId::Index(_) => {} @@ -191,7 +191,7 @@ pub(crate) fn build_index<'tcx>( lastpathid += 1; if let Some(&(ref fqp, short)) = paths.get(&defid) { - crate_paths.push((short, *fqp.last().unwrap())); + crate_paths.push((short, fqp.clone())); Some(pathid) } else { None @@ -213,118 +213,163 @@ pub(crate) fn build_index<'tcx>( struct CrateData<'a> { doc: String, items: Vec<&'a IndexItem>, - paths: Vec<(ItemType, Symbol)>, + paths: Vec<(ItemType, Vec<Symbol>)>, // The String is alias name and the vec is the list of the elements with this alias. // // To be noted: the `usize` elements are indexes to `items`. aliases: &'a BTreeMap<String, Vec<usize>>, } + struct Paths { + ty: ItemType, + name: Symbol, + path: Option<usize>, + } + + impl Serialize for Paths { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty)?; + seq.serialize_element(self.name.as_str())?; + if let Some(ref path) = self.path { + seq.serialize_element(path)?; + } + seq.end() + } + } + impl<'a> Serialize for CrateData<'a> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { + let mut extra_paths = FxHashMap::default(); + // We need to keep the order of insertion, hence why we use an `IndexMap`. Then we will + // insert these "extra paths" (which are paths of items from external crates) into the + // `full_paths` list at the end. + let mut revert_extra_paths = FxIndexMap::default(); + let mut mod_paths = FxHashMap::default(); + for (index, item) in self.items.iter().enumerate() { + if item.path.is_empty() { + continue; + } + mod_paths.insert(&item.path, index); + } + let mut paths = Vec::with_capacity(self.paths.len()); + for (ty, path) in &self.paths { + if path.len() < 2 { + paths.push(Paths { ty: *ty, name: path[0], path: None }); + continue; + } + let full_path = join_with_double_colon(&path[..path.len() - 1]); + if let Some(index) = mod_paths.get(&full_path) { + paths.push(Paths { ty: *ty, name: *path.last().unwrap(), path: Some(*index) }); + continue; + } + // It means it comes from an external crate so the item and its path will be + // stored into another array. + // + // `index` is put after the last `mod_paths` + let index = extra_paths.len() + self.items.len(); + if !revert_extra_paths.contains_key(&index) { + revert_extra_paths.insert(index, full_path.clone()); + } + match extra_paths.entry(full_path) { + Entry::Occupied(entry) => { + paths.push(Paths { + ty: *ty, + name: *path.last().unwrap(), + path: Some(*entry.get()), + }); + } + Entry::Vacant(entry) => { + entry.insert(index); + paths.push(Paths { + ty: *ty, + name: *path.last().unwrap(), + path: Some(index), + }); + } + } + } + + let mut names = Vec::with_capacity(self.items.len()); + let mut types = String::with_capacity(self.items.len()); + let mut full_paths = Vec::with_capacity(self.items.len()); + let mut descriptions = Vec::with_capacity(self.items.len()); + let mut parents = Vec::with_capacity(self.items.len()); + let mut functions = Vec::with_capacity(self.items.len()); + let mut deprecated = Vec::with_capacity(self.items.len()); + + for (index, item) in self.items.iter().enumerate() { + let n = item.ty as u8; + let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); + assert!(c <= 'z', "item types must fit within ASCII printables"); + types.push(c); + + assert_eq!( + item.parent.is_some(), + item.parent_idx.is_some(), + "`{}` is missing idx", + item.name + ); + // 0 is a sentinel, everything else is one-indexed + parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0)); + + names.push(item.name.as_str()); + descriptions.push(&item.desc); + + if !item.path.is_empty() { + full_paths.push((index, &item.path)); + } + + // Fake option to get `0` out as a sentinel instead of `null`. + // We want to use `0` because it's three less bytes. + enum FunctionOption<'a> { + Function(&'a IndexItemFunctionType), + None, + } + impl<'a> Serialize for FunctionOption<'a> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match self { + FunctionOption::None => 0.serialize(serializer), + FunctionOption::Function(ty) => ty.serialize(serializer), + } + } + } + functions.push(match &item.search_type { + Some(ty) => FunctionOption::Function(ty), + None => FunctionOption::None, + }); + + if item.deprecation.is_some() { + deprecated.push(index); + } + } + + for (index, path) in &revert_extra_paths { + full_paths.push((*index, path)); + } + let has_aliases = !self.aliases.is_empty(); let mut crate_data = serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?; crate_data.serialize_field("doc", &self.doc)?; - crate_data.serialize_field( - "t", - &self - .items - .iter() - .map(|item| { - let n = item.ty as u8; - let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); - assert!(c <= 'z', "item types must fit within ASCII printables"); - c - }) - .collect::<String>(), - )?; - crate_data.serialize_field( - "n", - &self.items.iter().map(|item| item.name.as_str()).collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "q", - &self - .items - .iter() - .enumerate() - // Serialize as an array of item indices and full paths - .filter_map( - |(index, item)| { - if item.path.is_empty() { None } else { Some((index, &item.path)) } - }, - ) - .collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "d", - &self.items.iter().map(|item| &item.desc).collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "i", - &self - .items - .iter() - .map(|item| { - assert_eq!( - item.parent.is_some(), - item.parent_idx.is_some(), - "`{}` is missing idx", - item.name - ); - // 0 is a sentinel, everything else is one-indexed - item.parent_idx.map(|x| x + 1).unwrap_or(0) - }) - .collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "f", - &self - .items - .iter() - .map(|item| { - // Fake option to get `0` out as a sentinel instead of `null`. - // We want to use `0` because it's three less bytes. - enum FunctionOption<'a> { - Function(&'a IndexItemFunctionType), - None, - } - impl<'a> Serialize for FunctionOption<'a> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - match self { - FunctionOption::None => 0.serialize(serializer), - FunctionOption::Function(ty) => ty.serialize(serializer), - } - } - } - match &item.search_type { - Some(ty) => FunctionOption::Function(ty), - None => FunctionOption::None, - } - }) - .collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "c", - &self - .items - .iter() - .enumerate() - // Serialize as an array of deprecated item indices - .filter_map(|(index, item)| item.deprecation.map(|_| index)) - .collect::<Vec<_>>(), - )?; - crate_data.serialize_field( - "p", - &self.paths.iter().map(|(it, s)| (it, s.as_str())).collect::<Vec<_>>(), - )?; + crate_data.serialize_field("t", &types)?; + crate_data.serialize_field("n", &names)?; + // Serialize as an array of item indices and full paths + crate_data.serialize_field("q", &full_paths)?; + crate_data.serialize_field("d", &descriptions)?; + crate_data.serialize_field("i", &parents)?; + crate_data.serialize_field("f", &functions)?; + crate_data.serialize_field("c", &deprecated)?; + crate_data.serialize_field("p", &paths)?; if has_aliases { crate_data.serialize_field("a", &self.aliases)?; } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 42088e73554..449168c460b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -263,7 +263,6 @@ function initSearch(rawSearchIndex) { * @returns {integer} */ function buildTypeMapIndex(name) { - if (name === "" || name === null) { return -1; } @@ -1380,7 +1379,7 @@ function initSearch(rawSearchIndex) { * @type Map<integer, QueryElement[]> */ const queryElemSet = new Map(); - const addQueryElemToQueryElemSet = function addQueryElemToQueryElemSet(queryElem) { + const addQueryElemToQueryElemSet = queryElem => { let currentQueryElemList; if (queryElemSet.has(queryElem.id)) { currentQueryElemList = queryElemSet.get(queryElem.id); @@ -1397,7 +1396,7 @@ function initSearch(rawSearchIndex) { * @type Map<integer, FunctionType[]> */ const fnTypeSet = new Map(); - const addFnTypeToFnTypeSet = function addFnTypeToFnTypeSet(fnType) { + const addFnTypeToFnTypeSet = fnType => { // Pure generic, or an item that's not matched by any query elems. // Try [unboxing] it. // @@ -1463,6 +1462,32 @@ function initSearch(rawSearchIndex) { if (!typePassesFilter(queryElem.typeFilter, fnType.ty)) { continue; } + const queryElemPathLength = queryElem.pathWithoutLast.length; + // If the query element is a path (it contains `::`), we need to check if this + // path is compatible with the target type. + if (queryElemPathLength > 0) { + const fnTypePath = fnType.path !== undefined && fnType.path !== null ? + fnType.path.split("::") : []; + // If the path provided in the query element is longer than this type, + // no need to check it since it won't match in any case. + if (queryElemPathLength > fnTypePath.length) { + continue; + } + let i = 0; + for (const path of fnTypePath) { + if (path === queryElem.pathWithoutLast[i]) { + i += 1; + if (i >= queryElemPathLength) { + break; + } + } + } + if (i < queryElemPathLength) { + // If we didn't find all parts of the path of the query element inside + // the fn type, then it's not the right one. + continue; + } + } if (queryElem.generics.length === 0 || checkGenerics(fnType, queryElem)) { currentFnTypeList.splice(i, 1); const result = doHandleQueryElemList(currentFnTypeList, queryElemList); @@ -1863,14 +1888,14 @@ function initSearch(rawSearchIndex) { * @param {QueryElement} elem */ function convertNameToId(elem) { - if (typeNameIdMap.has(elem.name)) { - elem.id = typeNameIdMap.get(elem.name); + if (typeNameIdMap.has(elem.pathLast)) { + elem.id = typeNameIdMap.get(elem.pathLast); } else if (!parsedQuery.literalSearch) { let match = -1; let matchDist = maxEditDistance + 1; let matchName = ""; for (const [name, id] of typeNameIdMap) { - const dist = editDistance(name, elem.name, maxEditDistance); + const dist = editDistance(name, elem.pathLast, maxEditDistance); if (dist <= matchDist && dist <= maxEditDistance) { if (dist === matchDist && matchName > name) { continue; @@ -2385,12 +2410,20 @@ ${item.displayPath}<span class="${type}">${name}</span>\ lowercasePaths ); } + // `0` is used as a sentinel because it's fewer bytes than `null` + if (pathIndex === 0) { + return { + id: -1, + ty: null, + path: null, + generics: generics, + }; + } + const item = lowercasePaths[pathIndex - 1]; return { - // `0` is used as a sentinel because it's fewer bytes than `null` - id: pathIndex === 0 - ? -1 - : buildTypeMapIndex(lowercasePaths[pathIndex - 1].name), - ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty, + id: buildTypeMapIndex(item.name), + ty: item.ty, + path: item.path, generics: generics, }; }); @@ -2422,13 +2455,22 @@ ${item.displayPath}<span class="${type}">${name}</span>\ let inputs, output; if (typeof functionSearchType[INPUTS_DATA] === "number") { const pathIndex = functionSearchType[INPUTS_DATA]; - inputs = [{ - id: pathIndex === 0 - ? -1 - : buildTypeMapIndex(lowercasePaths[pathIndex - 1].name), - ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty, - generics: [], - }]; + if (pathIndex === 0) { + inputs = [{ + id: -1, + ty: null, + path: null, + generics: [], + }]; + } else { + const item = lowercasePaths[pathIndex - 1]; + inputs = [{ + id: buildTypeMapIndex(item.name), + ty: item.ty, + path: item.path, + generics: [], + }]; + } } else { inputs = buildItemSearchTypeAll( functionSearchType[INPUTS_DATA], @@ -2438,13 +2480,22 @@ ${item.displayPath}<span class="${type}">${name}</span>\ if (functionSearchType.length > 1) { if (typeof functionSearchType[OUTPUT_DATA] === "number") { const pathIndex = functionSearchType[OUTPUT_DATA]; - output = [{ - id: pathIndex === 0 - ? -1 - : buildTypeMapIndex(lowercasePaths[pathIndex - 1].name), - ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty, - generics: [], - }]; + if (pathIndex === 0) { + output = [{ + id: -1, + ty: null, + path: null, + generics: [], + }]; + } else { + const item = lowercasePaths[pathIndex - 1]; + output = [{ + id: buildTypeMapIndex(item.name), + ty: item.ty, + path: item.path, + generics: [], + }]; + } } else { output = buildItemSearchTypeAll( functionSearchType[OUTPUT_DATA], @@ -2577,9 +2628,19 @@ ${item.displayPath}<span class="${type}">${name}</span>\ // 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) { - lowercasePaths.push({ty: paths[i][0], name: paths[i][1].toLowerCase()}); - paths[i] = {ty: paths[i][0], name: paths[i][1]}; + 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; + } + + lowercasePaths.push({ty: ty, name: name.toLowerCase(), path: path}); + paths[i] = {ty: ty, name: name, path: path}; } // convert `item*` into an object form, and construct word indices. @@ -2589,8 +2650,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\ // 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 lastPath = ""; for (let i = 0; i < len; ++i) { let word = ""; // This object should have exactly the same set of fields as the "crateRow" @@ -2599,11 +2660,12 @@ ${item.displayPath}<span class="${type}">${name}</span>\ word = itemNames[i].toLowerCase(); } searchWords.push(word); + const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; const row = { crate: crate, ty: itemTypes.charCodeAt(i) - charA, name: itemNames[i], - path: itemPaths.has(i) ? itemPaths.get(i) : lastPath, + path: path, desc: itemDescs[i], parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined, type: buildFunctionSearchType( diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 66b5798797f..0c18f5687f5 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -8,6 +8,7 @@ use std::fmt; use rustc_ast::ast; use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId}; +use rustc_metadata::rendered_const; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::{Pos, Symbol}; @@ -15,7 +16,6 @@ use rustc_target::spec::abi::Abi as RustcAbi; use rustdoc_json_types::*; -use crate::clean::utils::print_const_expr; use crate::clean::{self, ItemId}; use crate::formats::item_type::ItemType; use crate::json::JsonRenderer; @@ -805,7 +805,7 @@ impl FromWithTcx<clean::Static> for Static { Static { type_: stat.type_.into_tcx(tcx), mutable: stat.mutability == ast::Mutability::Mut, - expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(), + expr: stat.expr.map(|e| rendered_const(tcx, e)).unwrap_or_default(), } } } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 66876e02c19..f20b7a2b4d7 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -78,13 +78,22 @@ pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> { /// We will then fall back to origin/master in the hope that at least this exists. pub fn updated_master_branch(git_dir: Option<&Path>) -> Result<String, String> { let upstream_remote = get_rust_lang_rust_remote(git_dir)?; - let upstream_master = format!("{upstream_remote}/master"); - if rev_exists(&upstream_master, git_dir)? { - return Ok(upstream_master); + for upstream_master in [format!("{upstream_remote}/master"), format!("origin/master")] { + if rev_exists(&upstream_master, git_dir)? { + return Ok(upstream_master); + } } - // We could implement smarter logic here in the future. - Ok("origin/master".into()) + Err(format!("Cannot find any suitable upstream master branch")) +} + +pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result<String, String> { + let updated_master = updated_master_branch(git_dir)?; + let mut git = Command::new("git"); + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) } /// Returns the files that have been modified in the current branch compared to the master branch. @@ -94,20 +103,13 @@ pub fn get_git_modified_files( git_dir: Option<&Path>, extensions: &Vec<&str>, ) -> Result<Option<Vec<String>>, String> { - let Ok(updated_master) = updated_master_branch(git_dir) else { - return Ok(None); - }; - - let git = || { - let mut git = Command::new("git"); - if let Some(git_dir) = git_dir { - git.current_dir(git_dir); - } - git - }; + let merge_base = get_git_merge_base(git_dir)?; - let merge_base = output_result(git().arg("merge-base").arg(&updated_master).arg("HEAD"))?; - let files = output_result(git().arg("diff-index").arg("--name-only").arg(merge_base.trim()))? + let mut git = Command::new("git"); + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + let files = output_result(git.args(["diff-index", "--name-only", merge_base.trim()]))? .lines() .map(|s| s.trim().to_owned()) .filter(|f| { diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index f9108145cdb..a687c7d29b5 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,24 +1,20 @@ use super::ARITHMETIC_SIDE_EFFECTS; use clippy_utils::consts::{constant, constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::ty::type_diagnostic_name; use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; use rustc_span::source_map::{Span, Spanned}; +use rustc_span::symbol::sym; use rustc_span::Symbol; use {rustc_ast as ast, rustc_hir as hir}; -const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[ - ["f32", "f32"], - ["f64", "f64"], - ["std::num::Saturating", "*"], - ["std::num::Wrapping", "*"], - ["std::string::String", "str"], -]; +const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]]; const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"]; -const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"]; +const INTEGER_METHODS: &[Symbol] = &[sym::saturating_div, sym::wrapping_div, sym::wrapping_rem, sym::wrapping_rem_euclid]; #[derive(Debug)] pub struct ArithmeticSideEffects { @@ -53,7 +49,7 @@ impl ArithmeticSideEffects { allowed_unary, const_span: None, expr_span: None, - integer_methods: INTEGER_METHODS.iter().map(|el| Symbol::intern(el)).collect(), + integer_methods: INTEGER_METHODS.iter().copied().collect(), } } @@ -86,6 +82,38 @@ impl ArithmeticSideEffects { self.allowed_unary.contains(ty_string_elem) } + /// Verifies built-in types that have specific allowed operations + fn has_specific_allowed_type_and_operation( + cx: &LateContext<'_>, + lhs_ty: Ty<'_>, + op: &Spanned<hir::BinOpKind>, + rhs_ty: Ty<'_>, + ) -> bool { + let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem); + let is_non_zero_u = |symbol: Option<Symbol>| { + matches!( + symbol, + Some(sym::NonZeroU128 | sym::NonZeroU16 | sym::NonZeroU32 | sym::NonZeroU64 | sym::NonZeroU8 | sym::NonZeroUsize) + ) + }; + let is_sat_or_wrap = |ty: Ty<'_>| { + let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating); + let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping); + is_sat || is_wrap + }; + + // If the RHS is NonZeroU*, then division or module by zero will never occur + if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem { + return true; + } + // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module + if is_sat_or_wrap(lhs_ty) { + return !is_div_or_rem; + } + + false + } + // For example, 8i32 or &i64::MAX. fn is_integral(ty: Ty<'_>) -> bool { ty.peel_refs().is_integral() @@ -147,6 +175,9 @@ impl ArithmeticSideEffects { if self.has_allowed_binary(lhs_ty, rhs_ty) { return; } + if Self::has_specific_allowed_type_and_operation(cx, lhs_ty, op, rhs_ty) { + return; + } let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) { if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op.node { // At least for integers, shifts are already handled by the CTFE diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs index 8485b3eab71..def30f5903d 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs @@ -15,7 +15,7 @@ extern crate proc_macro_derive; -use core::num::{Saturating, Wrapping}; +use core::num::{NonZeroUsize, Saturating, Wrapping}; const ONE: i32 = 1; const ZERO: i32 = 0; @@ -493,4 +493,32 @@ pub fn issue_11262() { let _ = 2 / zero; } +pub fn issue_11392() { + fn example_div(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize { + unsigned / nonzero_unsigned + } + + fn example_rem(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize { + unsigned % nonzero_unsigned + } + + let (unsigned, nonzero_unsigned) = (0, NonZeroUsize::new(1).unwrap()); + example_div(unsigned, nonzero_unsigned); + example_rem(unsigned, nonzero_unsigned); +} + +pub fn issue_11393() { + fn example_div(x: Wrapping<i32>, maybe_zero: Wrapping<i32>) -> Wrapping<i32> { + x / maybe_zero + } + + fn example_rem(x: Wrapping<i32>, maybe_zero: Wrapping<i32>) -> Wrapping<i32> { + x % maybe_zero + } + + let [x, maybe_zero] = [1, 0].map(Wrapping); + example_div(x, maybe_zero); + example_rem(x, maybe_zero); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr index e9a626643ff..7f490748160 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr @@ -702,5 +702,17 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | 10 / a | ^^^^^^ -error: aborting due to 117 previous errors +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:512:9 + | +LL | x / maybe_zero + | ^^^^^^^^^^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:516:9 + | +LL | x % maybe_zero + | ^^^^^^^^^^^^^^ + +error: aborting due to 119 previous errors diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 919bc135fdf..b40e7f83f4f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -35e416303e6591a71ef6a91e006c602d2def3968 +a989e25f1b87949a886eab3da10324d14189fe95 diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 03dd9037808..816055cc4fe 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,7 +8,6 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(round_ties_even)] -#![feature(os_str_bytes)] #![feature(lint_reasons)] #![feature(trait_upcasting)] // Configure clippy and other lints diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index f08f0aad5e7..a94b1ddcd95 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -24,7 +24,7 @@ pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> { } #[cfg(not(unix))] pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> { - // We cannot use `from_os_str_bytes_unchecked` here since we can't trust `bytes`. + // We cannot use `from_encoded_bytes_unchecked` here since we can't trust `bytes`. let s = std::str::from_utf8(bytes) .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?; Ok(OsStr::new(s)) @@ -83,7 +83,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ptr: Pointer<Option<Provenance>>, size: u64, ) -> InterpResult<'tcx, (bool, u64)> { - let bytes = os_str.as_os_str_bytes(); + let bytes = os_str.as_encoded_bytes(); self.eval_context_mut().write_c_str(bytes, ptr, size) } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index beaef22075b..dd2da3d22f2 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1344,7 +1344,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut name = dir_entry.file_name(); // not a Path as there are no separators! name.push("\0"); // Add a NUL terminator - let name_bytes = name.as_os_str_bytes(); + let name_bytes = name.as_encoded_bytes(); let name_len = u64::try_from(name_bytes.len()).unwrap(); let dirent64_layout = this.libc_ty_layout("dirent64"); @@ -1698,7 +1698,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Cow::Borrowed(resolved.as_ref()), crate::shims::os_str::PathConversion::HostToTarget, ); - let mut path_bytes = resolved.as_os_str_bytes(); + let mut path_bytes = resolved.as_encoded_bytes(); let bufsize: usize = bufsize.try_into().unwrap(); if path_bytes.len() > bufsize { path_bytes = &path_bytes[..bufsize] diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index 47904926b48..0242a228068 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -6,7 +6,7 @@ use super::miri_extern; pub fn host_to_target_path(path: OsString) -> PathBuf { use std::ffi::{CStr, CString}; - // Once into_os_str_bytes is stable we can use it here. + // Once into_encoded_bytes is stable we can use it here. // (Unstable features would need feature flags in each test...) let path = CString::new(path.into_string().unwrap()).unwrap(); let mut out = Vec::with_capacity(1024); |
