diff --git a/Cargo.lock b/Cargo.lock index 273d63d1e5ea8..62dadbd6c999a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1808,9 +1808,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" dependencies = [ "rustc-std-workspace-core", ] @@ -4683,9 +4683,9 @@ checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" [[package]] name = "socket2" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" dependencies = [ "cfg-if", "libc", diff --git a/RELEASES.md b/RELEASES.md index 9ff0d14b353cd..36597b1864f25 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,152 @@ +Version 1.43.0 (2020-04-23) +========================== + +Language +-------- +- [Fixed using binary operations with `&{number}` (e.g. `&1.0`) not having + the type inferred correctly.][68129] +- [Attributes such as `#[cfg()]` can now be used on `if` expressions.][69201] + +**Syntax only changes** +- [Allow `type Foo: Ord` syntactically.][69361] +- [Fuse associated and extern items up to defaultness.][69194] +- [Syntactically allow `self` in all `fn` contexts.][68764] +- [Merge `fn` syntax + cleanup item parsing.][68728] +- [`item` macro fragments can be interpolated into `trait`s, `impl`s, and `extern` blocks.][69366] + For example, you may now write: + ```rust + macro_rules! mac_trait { + ($i:item) => { + trait T { $i } + } + } + mac_trait! { + fn foo() {} + } + ``` + +These are still rejected *semantically*, so you will likely receive an error but +these changes can be seen and parsed by macros and +conditional compilation. + + +Compiler +-------- +- [You can now pass multiple lint flags to rustc to override the previous + flags.][67885] For example; `rustc -D unused -A unused-variables` denies + everything in the `unused` lint group except `unused-variables` which + is explicitly allowed. However, passing `rustc -A unused-variables -D unused` denies + everything in the `unused` lint group **including** `unused-variables` since + the allow flag is specified before the deny flag (and therefore overridden). +- [rustc will now prefer your system MinGW libraries over its bundled libraries + if they are available on `windows-gnu`.][67429] +- [rustc now buffers errors/warnings printed in JSON.][69227] + +Libraries +--------- +- [`Arc<[T; N]>`, `Box<[T; N]>`, and `Rc<[T; N]>`, now implement + `TryFrom>`,`TryFrom>`, and `TryFrom>` + respectively.][69538] **Note** These conversions are only available when `N` + is `0..=32`. +- [You can now use associated constants on floats and integers directly, rather + than having to import the module.][68952] e.g. You can now write `u32::MAX` or + `f32::NAN` with no imports. +- [`u8::is_ascii` is now `const`.][68984] +- [`String` now implements `AsMut`.][68742] +- [Added the `primitive` module to `std` and `core`.][67637] This module + reexports Rust's primitive types. This is mainly useful in macros + where you want avoid these types being shadowed. +- [Relaxed some of the trait bounds on `HashMap` and `HashSet`.][67642] +- [`string::FromUtf8Error` now implements `Clone + Eq`.][68738] + +Stabilized APIs +--------------- +- [`Once::is_completed`] +- [`f32::LOG10_2`] +- [`f32::LOG2_10`] +- [`f64::LOG10_2`] +- [`f64::LOG2_10`] +- [`iter::once_with`] + +Cargo +----- +- [You can now set config `[profile]`s in your `.cargo/config`, or through + your environment.][cargo/7823] +- [Cargo will now set `CARGO_BIN_EXE_` pointing to a binary's + executable path when running integration tests or benchmarks.][cargo/7697] + `` is the name of your binary as-is e.g. If you wanted the executable + path for a binary named `my-program`you would use `env!("CARGO_BIN_EXE_my-program")`. + +Misc +---- +- [Certain checks in the `const_err` lint were deemed unrelated to const + evaluation][69185], and have been moved to the `unconditional_panic` and + `arithmetic_overflow` lints. + +Compatibility Notes +------------------- + +- [Having trailing syntax in the `assert!` macro is now a hard error.][69548] This + has been a warning since 1.36.0. +- [Fixed `Self` not having the correctly inferred type.][69340] This incorrectly + led to some instances being accepted, and now correctly emits a hard error. + +[69340]: https://github.com/rust-lang/rust/pull/69340 + +Internal Only +------------- +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of `rustc` and +related tools. + +- [All components are now built with `opt-level=3` instead of `2`.][67878] +- [Improved how rustc generates drop code.][67332] +- [Improved performance from `#[inline]`-ing certain hot functions.][69256] +- [traits: preallocate 2 Vecs of known initial size][69022] +- [Avoid exponential behaviour when relating types][68772] +- [Skip `Drop` terminators for enum variants without drop glue][68943] +- [Improve performance of coherence checks][68966] +- [Deduplicate types in the generator witness][68672] +- [Invert control in struct_lint_level.][68725] + +[67332]: https://github.com/rust-lang/rust/pull/67332/ +[67429]: https://github.com/rust-lang/rust/pull/67429/ +[67637]: https://github.com/rust-lang/rust/pull/67637/ +[67642]: https://github.com/rust-lang/rust/pull/67642/ +[67878]: https://github.com/rust-lang/rust/pull/67878/ +[67885]: https://github.com/rust-lang/rust/pull/67885/ +[68129]: https://github.com/rust-lang/rust/pull/68129/ +[68672]: https://github.com/rust-lang/rust/pull/68672/ +[68725]: https://github.com/rust-lang/rust/pull/68725/ +[68728]: https://github.com/rust-lang/rust/pull/68728/ +[68738]: https://github.com/rust-lang/rust/pull/68738/ +[68742]: https://github.com/rust-lang/rust/pull/68742/ +[68764]: https://github.com/rust-lang/rust/pull/68764/ +[68772]: https://github.com/rust-lang/rust/pull/68772/ +[68943]: https://github.com/rust-lang/rust/pull/68943/ +[68952]: https://github.com/rust-lang/rust/pull/68952/ +[68966]: https://github.com/rust-lang/rust/pull/68966/ +[68984]: https://github.com/rust-lang/rust/pull/68984/ +[69022]: https://github.com/rust-lang/rust/pull/69022/ +[69185]: https://github.com/rust-lang/rust/pull/69185/ +[69194]: https://github.com/rust-lang/rust/pull/69194/ +[69201]: https://github.com/rust-lang/rust/pull/69201/ +[69227]: https://github.com/rust-lang/rust/pull/69227/ +[69548]: https://github.com/rust-lang/rust/pull/69548/ +[69256]: https://github.com/rust-lang/rust/pull/69256/ +[69361]: https://github.com/rust-lang/rust/pull/69361/ +[69366]: https://github.com/rust-lang/rust/pull/69366/ +[69538]: https://github.com/rust-lang/rust/pull/69538/ +[cargo/7823]: https://github.com/rust-lang/cargo/pull/7823 +[cargo/7697]: https://github.com/rust-lang/cargo/pull/7697 +[`Once::is_completed`]: https://doc.rust-lang.org/std/sync/struct.Once.html#method.is_completed +[`f32::LOG10_2`]: https://doc.rust-lang.org/std/f32/consts/constant.LOG10_2.html +[`f32::LOG2_10`]: https://doc.rust-lang.org/std/f32/consts/constant.LOG2_10.html +[`f64::LOG10_2`]: https://doc.rust-lang.org/std/f64/consts/constant.LOG10_2.html +[`f64::LOG2_10`]: https://doc.rust-lang.org/std/f64/consts/constant.LOG2_10.html +[`iter::once_with`]: https://doc.rust-lang.org/std/iter/fn.once_with.html + + Version 1.42.0 (2020-03-12) ========================== diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0bf507f9ebbba..85c5d28bb8924 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -627,8 +627,14 @@ impl Step for RustdocJSStd { if let Some(ref nodejs) = builder.config.nodejs { let mut command = Command::new(nodejs); command - .arg(builder.src.join("src/tools/rustdoc-js-std/tester.js")) + .arg(builder.src.join("src/tools/rustdoc-js/tester.js")) + .arg("--crate-name") + .arg("std") + .arg("--resource-suffix") + .arg(crate::channel::CFG_RELEASE_NUM) + .arg("--doc-folder") .arg(builder.doc_out(self.target)) + .arg("--test-folder") .arg(builder.src.join("src/test/rustdoc-js-std")); builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage }); builder.run(&mut command); diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 717e32d4a0d8a..d9620a21d37cd 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -15,7 +15,7 @@ cc = "1.0.1" num_cpus = "1.0" memmap = "0.7" log = "0.4.5" -libc = "0.2.44" +libc = "0.2.50" jobserver = "0.1.11" tempfile = "3.1" diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index d58d9b91c73ac..4c66d901e7a99 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -761,7 +761,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { } } LinkerFlavor::Gcc => { - if cfg!(target_os = "solaris") { + if cfg!(any(target_os = "solaris", target_os = "illumos")) { // On historical Solaris systems, "cc" may have // been Sun Studio, which is not flag-compatible // with "gcc". This history casts a long shadow, diff --git a/src/librustc_error_codes/error_codes/E0518.md b/src/librustc_error_codes/error_codes/E0518.md index 1af9a3735fe1a..f04329bc4e618 100644 --- a/src/librustc_error_codes/error_codes/E0518.md +++ b/src/librustc_error_codes/error_codes/E0518.md @@ -1,7 +1,7 @@ -This error indicates that an `#[inline(..)]` attribute was incorrectly placed -on something other than a function or method. +An `#[inline(..)]` attribute was incorrectly placed on something other than a +function or method. -Examples of erroneous code: +Example of erroneous code: ```compile_fail,E0518 #[inline(always)] diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 8d50f560a8370..430ff67d56b68 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -2399,7 +2399,11 @@ impl<'tcx> AdtDef { None } Err(ErrorHandled::TooGeneric) => { - span_bug!(tcx.def_span(expr_did), "enum discriminant depends on generic arguments",) + tcx.sess.delay_span_bug( + tcx.def_span(expr_did), + "enum discriminant depends on generic arguments", + ); + None } } } diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 21d632b9f6b83..d2d99cf030d96 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast, }; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; -use rustc_middle::ty::{self, AdtKind, Ty}; +use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; use rustc_span::Span; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr<'tcx> { @@ -718,8 +718,7 @@ fn convert_path_expr<'a, 'tcx>( Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => { let user_provided_types = cx.tables.user_provided_types(); - let user_provided_type = user_provided_types.get(expr.hir_id).copied(); - debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); + let user_ty = user_provided_types.get(expr.hir_id).copied(); let ty = cx.tables().node_type(expr.hir_id); match ty.kind { // A unit struct/variant which is used as a value. @@ -728,10 +727,17 @@ fn convert_path_expr<'a, 'tcx>( adt_def, variant_index: adt_def.variant_index_with_ctor_id(def_id), substs, - user_ty: user_provided_type, + user_ty, fields: vec![], base: None, }, + _ if ty.references_error() => { + // Handle degenerate input without ICE (#67377). + ExprKind::Literal { + literal: ty::Const::zero_sized(cx.tcx, cx.tcx.types.err), + user_ty: None, + } + } _ => bug!("unexpected ty: {:?}", ty), } } diff --git a/src/librustc_target/spec/illumos_base.rs b/src/librustc_target/spec/illumos_base.rs new file mode 100644 index 0000000000000..35ac346fb3f6f --- /dev/null +++ b/src/librustc_target/spec/illumos_base.rs @@ -0,0 +1,48 @@ +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut late_link_args = LinkArgs::new(); + late_link_args.insert( + LinkerFlavor::Gcc, + vec![ + // LLVM will insert calls to the stack protector functions + // "__stack_chk_fail" and "__stack_chk_guard" into code in native + // object files. Some platforms include these symbols directly in + // libc, but at least historically these have been provided in + // libssp.so on illumos and Solaris systems. + "-lssp".to_string(), + ], + ); + + TargetOptions { + dynamic_linking: true, + executables: true, + has_rpath: true, + target_family: Some("unix".to_string()), + is_like_solaris: true, + limit_rdylib_exports: false, // Linker doesn't support this + eliminate_frame_pointer: false, + late_link_args, + + // While we support ELF TLS, rust requires a way to register + // cleanup handlers (in C, this would be something along the lines of: + // void register_callback(void (*fn)(void *), void *arg); + // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently + // missing in illumos. For now at least, we must fallback to using + // pthread_{get,set}specific. + //has_elf_tls: true, + + // FIXME: Currently, rust is invoking cc to link, which ends up + // causing these to get included twice. We should eventually transition + // to having rustc invoke ld directly, in which case these will need to + // be uncommented. + // + // We want XPG6 behavior from libc and libm. See standards(5) + //pre_link_objects_exe: vec![ + // "/usr/lib/amd64/values-Xc.o".to_string(), + // "/usr/lib/amd64/values-xpg6.o".to_string(), + //], + ..Default::default() + } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 6ff812754aa7d..8f3097ad4233e 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -55,6 +55,7 @@ mod fuchsia_base; mod haiku_base; mod hermit_base; mod hermit_kernel_base; +mod illumos_base; mod l4re_base; mod linux_base; mod linux_kernel_base; @@ -438,6 +439,8 @@ supported_targets! { ("x86_64-sun-solaris", "x86_64-pc-solaris", x86_64_sun_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), + ("x86_64-unknown-illumos", x86_64_unknown_illumos), + ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), ("i686-uwp-windows-gnu", i686_uwp_windows_gnu), diff --git a/src/librustc_target/spec/x86_64_unknown_illumos.rs b/src/librustc_target/spec/x86_64_unknown_illumos.rs new file mode 100644 index 0000000000000..8d461f67397f2 --- /dev/null +++ b/src/librustc_target/spec/x86_64_unknown_illumos.rs @@ -0,0 +1,24 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::illumos_base::opts(); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string(), "-std=c99".to_string()]); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + + Ok(Target { + // LLVM does not currently have a separate illumos target, + // so we still pass Solaris to it + llvm_target: "x86_64-pc-solaris".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "illumos".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 775d600fc3d4b..57d499e38a77b 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -360,6 +360,7 @@ impl<'a> fmt::Display for Html<'a> { "fuchsia" => "Fuchsia", "haiku" => "Haiku", "hermit" => "HermitCore", + "illumos" => "illumos", "ios" => "iOS", "l4re" => "L4Re", "linux" => "Linux", diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 316cf84152842..2626ca638e841 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -208,10 +208,10 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - if let Some(did) = ty.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - res.insert((ty, kind)); - } + if let Some(kind) = + ty.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) + { + res.insert((ty, kind)); } } } @@ -226,20 +226,18 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - if let Some(did) = ty.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - res.insert((ty.clone(), kind)); - } + if let Some(kind) = + ty.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) + { + res.insert((ty.clone(), kind)); } } } } } } else { - if let Some(did) = arg.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - res.insert((arg.clone(), kind)); - } + if let Some(kind) = arg.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) { + res.insert((arg.clone(), kind)); } if let Some(gens) = arg.generics() { for gen in gens.iter() { @@ -248,10 +246,10 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } - } else if let Some(did) = gen.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - res.insert((gen.clone(), kind)); - } + } else if let Some(kind) = + gen.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) + { + res.insert((gen.clone(), kind)); } } } @@ -277,10 +275,8 @@ pub fn get_all_types( if !args.is_empty() { all_types.extend(args); } else { - if let Some(did) = arg.type_.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - all_types.insert((arg.type_.clone(), kind)); - } + if let Some(kind) = arg.type_.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) { + all_types.insert((arg.type_.clone(), kind)); } } } @@ -289,10 +285,10 @@ pub fn get_all_types( FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { - if let Some(did) = return_type.def_id() { - if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { - ret.insert((return_type.clone(), kind)); - } + if let Some(kind) = + return_type.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) + { + ret.insert((return_type.clone(), kind)); } } ret.into_iter().collect() diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index d9f6f7b466a1f..a8efb16a1d31e 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -697,11 +697,11 @@ fn get_generics(clean_type: &clean::Type) -> Option> { let r = types .iter() .filter_map(|t| { - if let Some(name) = get_index_type_name(t, false) { - Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None }) - } else { - None - } + get_index_type_name(t, false).map(|name| Generic { + name: name.to_ascii_lowercase(), + defid: t.def_id(), + idx: None, + }) }) .collect::>(); if r.is_empty() { None } else { Some(r) } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 8db7bc12cd308..743a1778fbda3 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -25,6 +25,14 @@ fn main() { println!("cargo:rustc-link-lib=posix4"); println!("cargo:rustc-link-lib=pthread"); println!("cargo:rustc-link-lib=resolv"); + } else if target.contains("illumos") { + println!("cargo:rustc-link-lib=socket"); + println!("cargo:rustc-link-lib=posix4"); + println!("cargo:rustc-link-lib=pthread"); + println!("cargo:rustc-link-lib=resolv"); + println!("cargo:rustc-link-lib=nsl"); + // Use libumem for the (malloc-compatible) allocator + println!("cargo:rustc-link-lib=umem"); } else if target.contains("apple-darwin") { println!("cargo:rustc-link-lib=System"); diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index ff222fc8539d0..5cf9cb73d4bf9 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -919,7 +919,7 @@ impl f64 { // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). fn log_wrapper f64>(self, log_fn: F) -> f64 { - if !cfg!(target_os = "solaris") { + if !cfg!(any(target_os = "solaris", target_os = "illumos")) { log_fn(self) } else { if self.is_finite() { diff --git a/src/libstd/os/illumos/fs.rs b/src/libstd/os/illumos/fs.rs new file mode 100644 index 0000000000000..2abbf1fa9fa16 --- /dev/null +++ b/src/libstd/os/illumos/fs.rs @@ -0,0 +1,118 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use libc; + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +#[allow(deprecated)] +use crate::os::illumos::raw; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Gain a reference to the underlying `stat` structure which contains + /// the raw information returned by the OS. + /// + /// The contents of the returned `stat` are **not** consistent across + /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the + /// cross-Unix abstractions contained within the raw stat. + #[stable(feature = "metadata_ext", since = "1.1.0")] + #[rustc_deprecated( + since = "1.8.0", + reason = "deprecated in favor of the accessor methods of this trait" + )] + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat; + + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat { + unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } + } + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/src/libstd/os/illumos/mod.rs b/src/libstd/os/illumos/mod.rs new file mode 100644 index 0000000000000..e61926f89356a --- /dev/null +++ b/src/libstd/os/illumos/mod.rs @@ -0,0 +1,6 @@ +//! illumos-specific definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; diff --git a/src/libstd/os/illumos/raw.rs b/src/libstd/os/illumos/raw.rs new file mode 100644 index 0000000000000..88c832ae7c773 --- /dev/null +++ b/src/libstd/os/illumos/raw.rs @@ -0,0 +1,74 @@ +//! illumos-specific raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![rustc_deprecated( + since = "1.8.0", + reason = "these type aliases are no longer supported by the standard library, the `libc` \ + crate on crates.io should be used instead for the correct definitions" +)] +#![allow(deprecated)] + +use crate::os::raw::c_long; +use crate::os::unix::raw::{gid_t, uid_t}; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type fflags_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = i64; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = u32; + +#[repr(C)] +#[derive(Clone)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: ino_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: mode_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: nlink_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: uid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: gid_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: off_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: blksize_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: blkcnt_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __unused: [u8; 16], +} diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 0fa4a1d2353ca..fd6ee088e961c 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -52,6 +52,8 @@ pub mod freebsd; pub mod fuchsia; #[cfg(target_os = "haiku")] pub mod haiku; +#[cfg(target_os = "illumos")] +pub mod illumos; #[cfg(target_os = "ios")] pub mod ios; #[cfg(target_os = "macos")] diff --git a/src/libstd/sys/unix/alloc.rs b/src/libstd/sys/unix/alloc.rs index 77417e4133127..8e193935460eb 100644 --- a/src/libstd/sys/unix/alloc.rs +++ b/src/libstd/sys/unix/alloc.rs @@ -52,7 +52,12 @@ unsafe impl GlobalAlloc for System { } } -#[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))] +#[cfg(any( + target_os = "android", + target_os = "illumos", + target_os = "redox", + target_os = "solaris" +))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { // On android we currently target API level 9 which unfortunately @@ -75,7 +80,12 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { libc::memalign(layout.align(), layout.size()) as *mut u8 } -#[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))] +#[cfg(not(any( + target_os = "android", + target_os = "illumos", + target_os = "redox", + target_os = "solaris" +)))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 09acc3f6e3ea8..4c3e8542d576d 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -65,6 +65,7 @@ impl DoubleEndedIterator for Args { target_os = "netbsd", target_os = "openbsd", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "haiku", target_os = "l4re", diff --git a/src/libstd/sys/unix/env.rs b/src/libstd/sys/unix/env.rs index 984bcfa45099b..7f5e9b04dba4b 100644 --- a/src/libstd/sys/unix/env.rs +++ b/src/libstd/sys/unix/env.rs @@ -97,6 +97,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "illumos")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "illumos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "haiku")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 8a99836912a33..1bba56e334a2e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -153,6 +153,7 @@ impl FileDesc { #[cfg(not(any( target_env = "newlib", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "fuchsia", target_os = "l4re", @@ -169,6 +170,7 @@ impl FileDesc { #[cfg(any( target_env = "newlib", target_os = "solaris", + target_os = "illumos", target_os = "emscripten", target_os = "fuchsia", target_os = "l4re", diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index ab2a871b92df4..a233aa47dff58 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -22,6 +22,7 @@ use libc::fstatat64; target_os = "linux", target_os = "emscripten", target_os = "solaris", + target_os = "illumos", target_os = "l4re", target_os = "fuchsia", target_os = "redox" @@ -200,7 +201,12 @@ pub struct DirEntry { // on Solaris and Fuchsia because a) it uses a zero-length // array to store the name, b) its lifetime between readdir // calls is not guaranteed. - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + ))] name: Box<[u8]>, } @@ -403,7 +409,12 @@ impl fmt::Debug for ReadDir { impl Iterator for ReadDir { type Item = io::Result; - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any( + target_os = "solaris", + target_os = "fuchsia", + target_os = "redox", + target_os = "illumos" + ))] fn next(&mut self) -> Option> { use crate::slice; @@ -441,7 +452,12 @@ impl Iterator for ReadDir { } } - #[cfg(not(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox")))] + #[cfg(not(any( + target_os = "solaris", + target_os = "fuchsia", + target_os = "redox", + target_os = "illumos" + )))] fn next(&mut self) -> Option> { if self.end_of_stream { return None; @@ -514,12 +530,12 @@ impl DirEntry { lstat(&self.path()) } - #[cfg(any(target_os = "solaris", target_os = "haiku"))] + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "haiku"))] pub fn file_type(&self) -> io::Result { lstat(&self.path()).map(|m| m.file_type()) } - #[cfg(not(any(target_os = "solaris", target_os = "haiku")))] + #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "haiku")))] pub fn file_type(&self) -> io::Result { match self.entry.d_type { libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }), @@ -540,6 +556,7 @@ impl DirEntry { target_os = "emscripten", target_os = "android", target_os = "solaris", + target_os = "illumos", target_os = "haiku", target_os = "l4re", target_os = "fuchsia", @@ -586,7 +603,12 @@ impl DirEntry { fn name_bytes(&self) -> &[u8] { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() } } - #[cfg(any(target_os = "solaris", target_os = "fuchsia", target_os = "redox"))] + #[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "fuchsia", + target_os = "redox" + ))] fn name_bytes(&self) -> &[u8] { &*self.name } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index fbcb006ecdf11..0154609d939f3 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -17,6 +17,8 @@ pub use crate::os::freebsd as platform; pub use crate::os::fuchsia as platform; #[cfg(all(not(doc), target_os = "haiku"))] pub use crate::os::haiku as platform; +#[cfg(all(not(doc), target_os = "illumos"))] +pub use crate::os::illumos as platform; #[cfg(all(not(doc), target_os = "ios"))] pub use crate::os::ios as platform; #[cfg(all(not(doc), target_os = "l4re"))] diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index b37675e0a0a00..d18c22b0573f3 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -322,11 +322,19 @@ impl Socket { Ok(raw != 0) } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int; cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(drop) } + #[cfg(any(target_os = "solaris", target_os = "illumos"))] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + // FIONBIO is inadequate for sockets on illumos/Solaris, so use the + // fcntl(F_[GS]ETFL)-based method provided by FileDesc instead. + self.0.set_nonblocking(nonblocking) + } + pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 91f7d1524ccef..a9cd5094997bd 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -54,7 +54,7 @@ extern "C" { ), link_name = "__errno" )] - #[cfg_attr(target_os = "solaris", link_name = "___errno")] + #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] #[cfg_attr( any(target_os = "macos", target_os = "ios", target_os = "freebsd"), link_name = "__error" @@ -357,7 +357,7 @@ pub fn current_exe() -> io::Result { } } -#[cfg(any(target_os = "solaris"))] +#[cfg(any(target_os = "solaris", target_os = "illumos"))] pub fn current_exe() -> io::Result { extern "C" { fn getexecname() -> *const c_char; diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 2626ca37cf8b8..5e10357835056 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -33,6 +33,7 @@ impl Drop for Handler { target_os = "dragonfly", target_os = "freebsd", target_os = "solaris", + target_os = "illumos", all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd" ))] @@ -162,7 +163,8 @@ mod imp { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos" ))] unsafe fn get_stack() -> libc::stack_t { libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ } @@ -214,6 +216,7 @@ mod imp { target_os = "dragonfly", target_os = "freebsd", target_os = "solaris", + target_os = "illumos", all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd" )))] diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index aab5a92a7ad2a..895ea48e2b43e 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -132,7 +132,7 @@ impl Thread { } } - #[cfg(target_os = "solaris")] + #[cfg(any(target_os = "solaris", target_os = "illumos"))] pub fn set_name(name: &CStr) { weak! { fn pthread_setname_np( @@ -155,7 +155,7 @@ impl Thread { target_os = "redox" ))] pub fn set_name(_name: &CStr) { - // Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name. + // Newlib, Haiku, and Emscripten have no way to set a thread name. } #[cfg(target_os = "fuchsia")] pub fn set_name(_name: &CStr) { diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 135e8308afaea..cdd3d2edf1fa1 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -17,7 +17,7 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", - target_os = "openbsd", target_os = "netbsd", + target_os = "openbsd", target_os = "netbsd", target_os = "illumos", target_os = "solaris", target_os = "haiku", target_os = "l4re"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; @@ -43,7 +43,7 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "solaris"))] { + target_os = "solaris", target_os = "illumos"))] { use libc::c_uchar; type IpV4MultiCastType = c_uchar; } else { diff --git a/src/libtest/helpers/concurrency.rs b/src/libtest/helpers/concurrency.rs index 6b0c8a8af32b4..e8f3820558a6d 100644 --- a/src/libtest/helpers/concurrency.rs +++ b/src/libtest/helpers/concurrency.rs @@ -77,6 +77,7 @@ pub fn get_concurrency() -> usize { target_os = "linux", target_os = "macos", target_os = "solaris", + target_os = "illumos", ))] fn num_cpus() -> usize { unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize } diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index 0628e5d2fc03a..c8d2419ab4514 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -30,6 +30,8 @@ fn main() { } } else if target.contains("solaris") { println!("cargo:rustc-link-lib=gcc_s"); + } else if target.contains("illumos") { + println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("dragonfly") { println!("cargo:rustc-link-lib=gcc_pic"); } else if target.contains("pc-windows-gnu") { diff --git a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.rs b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.rs new file mode 100644 index 0000000000000..87222ef4b5924 --- /dev/null +++ b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.rs @@ -0,0 +1,35 @@ +mod a { + use std::marker::PhantomData; + + enum Bug { + V = [PhantomData; { [ () ].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + } +} + +mod b { + enum Bug { + V = [Vec::new; { [].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR type annotations needed + } +} + +mod c { + enum Bug { + V = [Vec::new; { [0].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR type annotations needed + } +} + +fn main() {} diff --git a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr new file mode 100644 index 0000000000000..f20ec75535354 --- /dev/null +++ b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr @@ -0,0 +1,123 @@ +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - - ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error[E0282]: type annotations needed + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:29 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | ^^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | ^^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index f075d3e22d664..6de07d3e5cfd8 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -139,6 +139,7 @@ static TARGETS: &[&str] = &[ "x86_64-pc-solaris", "x86_64-unknown-cloudabi", "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 70091bdbe6386..61a7d8ee5c948 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2810,10 +2810,16 @@ impl<'test> TestCx<'test> { self.document(&out_dir); let root = self.config.find_rust_src_root().unwrap(); + let file_stem = + self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem"); let res = self.cmd2procres( Command::new(&nodejs) .arg(root.join("src/tools/rustdoc-js/tester.js")) - .arg(out_dir.parent().expect("no parent")) + .arg("--doc-folder") + .arg(out_dir) + .arg("--crate-name") + .arg(file_stem.replace("-", "_")) + .arg("--test-file") .arg(self.testpaths.file.with_extension("js")), ); if !res.status.success() { diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 2663b3d160a7a..c61bee0f8d9ea 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -21,6 +21,7 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("fuchsia", "fuchsia"), ("haiku", "haiku"), ("hermit", "hermit"), + ("illumos", "illumos"), ("ios", "ios"), ("l4re", "l4re"), ("linux", "linux"), diff --git a/src/tools/rustdoc-js-common/lib.js b/src/tools/rustdoc-js-common/lib.js deleted file mode 100644 index 81e64aec491a6..0000000000000 --- a/src/tools/rustdoc-js-common/lib.js +++ /dev/null @@ -1,319 +0,0 @@ -const fs = require('fs'); - -function getNextStep(content, pos, stop) { - while (pos < content.length && content[pos] !== stop && - (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) { - pos += 1; - } - if (pos >= content.length) { - return null; - } - if (content[pos] !== stop) { - return pos * -1; - } - return pos; -} - -// Stupid function extractor based on indent. Doesn't support block -// comments. If someone puts a ' or an " in a block comment this -// will blow up. Template strings are not tested and might also be -// broken. -function extractFunction(content, functionName) { - var indent = 0; - var splitter = "function " + functionName + "("; - - while (true) { - var start = content.indexOf(splitter); - if (start === -1) { - break; - } - var pos = start; - while (pos < content.length && content[pos] !== ')') { - pos += 1; - } - if (pos >= content.length) { - break; - } - pos = getNextStep(content, pos + 1, '{'); - if (pos === null) { - break; - } else if (pos < 0) { - content = content.slice(-pos); - continue; - } - while (pos < content.length) { - // Eat single-line comments - if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') { - do { - pos += 1; - } while (pos < content.length && content[pos] !== '\n'); - - // Eat quoted strings - } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") { - var stop = content[pos]; - var is_escaped = false; - do { - if (content[pos] === '\\') { - pos += 2; - } else { - pos += 1; - } - } while (pos < content.length && - (content[pos] !== stop || content[pos - 1] === '\\')); - - // Otherwise, check for indent - } else if (content[pos] === '{') { - indent += 1; - } else if (content[pos] === '}') { - indent -= 1; - if (indent === 0) { - return content.slice(start, pos + 1); - } - } - pos += 1; - } - content = content.slice(start + 1); - } - return null; -} - -// Stupid function extractor for array. -function extractArrayVariable(content, arrayName) { - var splitter = "var " + arrayName; - while (true) { - var start = content.indexOf(splitter); - if (start === -1) { - break; - } - var pos = getNextStep(content, start, '='); - if (pos === null) { - break; - } else if (pos < 0) { - content = content.slice(-pos); - continue; - } - pos = getNextStep(content, pos, '['); - if (pos === null) { - break; - } else if (pos < 0) { - content = content.slice(-pos); - continue; - } - while (pos < content.length) { - if (content[pos] === '"' || content[pos] === "'") { - var stop = content[pos]; - do { - if (content[pos] === '\\') { - pos += 2; - } else { - pos += 1; - } - } while (pos < content.length && - (content[pos] !== stop || content[pos - 1] === '\\')); - } else if (content[pos] === ']' && - pos + 1 < content.length && - content[pos + 1] === ';') { - return content.slice(start, pos + 2); - } - pos += 1; - } - content = content.slice(start + 1); - } - return null; -} - -// Stupid function extractor for variable. -function extractVariable(content, varName) { - var splitter = "var " + varName; - while (true) { - var start = content.indexOf(splitter); - if (start === -1) { - break; - } - var pos = getNextStep(content, start, '='); - if (pos === null) { - break; - } else if (pos < 0) { - content = content.slice(-pos); - continue; - } - while (pos < content.length) { - if (content[pos] === '"' || content[pos] === "'") { - var stop = content[pos]; - do { - if (content[pos] === '\\') { - pos += 2; - } else { - pos += 1; - } - } while (pos < content.length && - (content[pos] !== stop || content[pos - 1] === '\\')); - } else if (content[pos] === ';' || content[pos] === ',') { - return content.slice(start, pos + 1); - } - pos += 1; - } - content = content.slice(start + 1); - } - return null; -} - -function loadContent(content) { - var Module = module.constructor; - var m = new Module(); - m._compile(content, "tmp.js"); - m.exports.ignore_order = content.indexOf("\n// ignore-order\n") !== -1 || - content.startsWith("// ignore-order\n"); - m.exports.exact_check = content.indexOf("\n// exact-check\n") !== -1 || - content.startsWith("// exact-check\n"); - m.exports.should_fail = content.indexOf("\n// should-fail\n") !== -1 || - content.startsWith("// should-fail\n"); - return m.exports; -} - -function readFile(filePath) { - return fs.readFileSync(filePath, 'utf8'); -} - -function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { - var content = ''; - for (var i = 0; i < thingsToLoad.length; ++i) { - var tmp = funcToCall(fileContent, thingsToLoad[i]); - if (tmp === null) { - console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); - process.exit(1); - } - content += tmp; - content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';'; - } - return content; -} - -function lookForEntry(entry, data) { - for (var i = 0; i < data.length; ++i) { - var allGood = true; - for (var key in entry) { - if (!entry.hasOwnProperty(key)) { - continue; - } - var value = data[i][key]; - // To make our life easier, if there is a "parent" type, we add it to the path. - if (key === 'path' && data[i]['parent'] !== undefined) { - if (value.length > 0) { - value += '::' + data[i]['parent']['name']; - } else { - value = data[i]['parent']['name']; - } - } - if (value !== entry[key]) { - allGood = false; - break; - } - } - if (allGood === true) { - return i; - } - } - return null; -} - -function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { - if (searchIndex[searchIndex.length - 1].length === 0) { - searchIndex.pop(); - } - searchIndex.pop(); - searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;'); - finalJS = ""; - - var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", - "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", - "TY_PRIMITIVE", "TY_KEYWORD", - "levenshtein_row2"]; - // execQuery first parameter is built in getQuery (which takes in the search input). - // execQuery last parameter is built in buildIndex. - // buildIndex requires the hashmap from search-index. - var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", - "getQuery", "buildIndex", "execQuery", "execSearch"]; - - finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; - finalJS += 'var rootPath = "../";\n'; - finalJS += aliases; - finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); - finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); - finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); - - var loaded = loadContent(finalJS); - var index = loaded.buildIndex(searchIndex.searchIndex); - - return [loaded, index]; -} - -function runChecks(testFile, loaded, index) { - var errors = 0; - var loadedFile = loadContent( - readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); - - const expected = loadedFile.EXPECTED; - const query = loadedFile.QUERY; - const filter_crate = loadedFile.FILTER_CRATE; - const ignore_order = loadedFile.ignore_order; - const exact_check = loadedFile.exact_check; - const should_fail = loadedFile.should_fail; - - var results = loaded.execSearch(loaded.getQuery(query), index); - var error_text = []; - - for (var key in expected) { - if (!expected.hasOwnProperty(key)) { - continue; - } - if (!results.hasOwnProperty(key)) { - error_text.push('==> Unknown key "' + key + '"'); - break; - } - var entry = expected[key]; - var prev_pos = -1; - for (var i = 0; i < entry.length; ++i) { - var entry_pos = lookForEntry(entry[i], results[key]); - if (entry_pos === null) { - error_text.push("==> Result not found in '" + key + "': '" + - JSON.stringify(entry[i]) + "'"); - } else if (exact_check === true && prev_pos + 1 !== entry_pos) { - error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " + - "expected '" + JSON.stringify(entry[i]) + "' but found '" + - JSON.stringify(results[key][i]) + "'"); - } else if (ignore_order === false && entry_pos < prev_pos) { - error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + - " before '" + JSON.stringify(results[key][entry_pos]) + "'"); - } else { - prev_pos = entry_pos; - } - } - } - if (error_text.length === 0 && should_fail === true) { - errors += 1; - console.error("FAILED"); - console.error("==> Test was supposed to fail but all items were found..."); - } else if (error_text.length !== 0 && should_fail === false) { - errors += 1; - console.error("FAILED"); - console.error(error_text.join("\n")); - } else { - console.log("OK"); - } - return errors; -} - -module.exports = { - 'getNextStep': getNextStep, - 'extractFunction': extractFunction, - 'extractArrayVariable': extractArrayVariable, - 'extractVariable': extractVariable, - 'loadContent': loadContent, - 'readFile': readFile, - 'loadThings': loadThings, - 'lookForEntry': lookForEntry, - 'loadMainJsAndIndex': loadMainJsAndIndex, - 'runChecks': runChecks, -}; diff --git a/src/tools/rustdoc-js-std/tester.js b/src/tools/rustdoc-js-std/tester.js deleted file mode 100644 index 6f730b0fdbbaa..0000000000000 --- a/src/tools/rustdoc-js-std/tester.js +++ /dev/null @@ -1,74 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const tools = require('../rustdoc-js-common/lib.js'); - - -function findFile(dir, name, extension) { - var entries = fs.readdirSync(dir); - var matches = []; - for (var i = 0; i < entries.length; ++i) { - var entry = entries[i]; - var file_type = fs.statSync(dir + entry); - if (file_type.isDirectory()) { - continue; - } - if (entry.startsWith(name) && entry.endsWith(extension)) { - var version = entry.slice(name.length, entry.length - extension.length); - version = version.split(".").map(function(x) { - return parseInt(x); - }); - var total = 0; - var mult = 1; - for (var j = version.length - 1; j >= 0; --j) { - total += version[j] * mult; - mult *= 1000; - } - matches.push([entry, total]); - } - } - if (matches.length === 0) { - return null; - } - // We make a reverse sort to have the "highest" file. Very useful in case you didn't clean up - // you std doc folder... - matches.sort(function(a, b) { - return b[1] - a[1]; - }); - return matches[0][0]; -} - -function readFileMatching(dir, name, extension) { - if (dir.endsWith("/") === false) { - dir += "/"; - } - var f = findFile(dir, name, extension); - if (f === null) { - return ""; - } - return tools.readFile(dir + f); -} - -function main(argv) { - if (argv.length !== 4) { - console.error("USAGE: node tester.js STD_DOCS TEST_FOLDER"); - return 1; - } - var std_docs = argv[2]; - var test_folder = argv[3]; - - var mainJs = readFileMatching(std_docs, "main", ".js"); - var aliases = readFileMatching(std_docs, "aliases", ".js"); - var searchIndex = readFileMatching(std_docs, "search-index", ".js").split("\n"); - - var [loaded, index] = tools.loadMainJsAndIndex(mainJs, aliases, searchIndex, "std"); - - var errors = 0; - - fs.readdirSync(test_folder).forEach(function(file) { - process.stdout.write('Checking "' + file + '" ... '); - errors += tools.runChecks(path.join(test_folder, file), loaded, index); - }); - return errors > 0 ? 1 : 0; -} - -process.exit(main(process.argv)); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 2e8901d56d01e..03f06fc1c6c71 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -1,43 +1,408 @@ const fs = require('fs'); const path = require('path'); -const tools = require('../rustdoc-js-common/lib.js'); -function load_files(out_folder, crate) { - var mainJs = tools.readFile(out_folder + "/main.js"); - var aliases = tools.readFile(out_folder + "/aliases.js"); - var searchIndex = tools.readFile(out_folder + "/search-index.js").split("\n"); +function getNextStep(content, pos, stop) { + while (pos < content.length && content[pos] !== stop && + (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) { + pos += 1; + } + if (pos >= content.length) { + return null; + } + if (content[pos] !== stop) { + return pos * -1; + } + return pos; +} + +// Stupid function extractor based on indent. Doesn't support block +// comments. If someone puts a ' or an " in a block comment this +// will blow up. Template strings are not tested and might also be +// broken. +function extractFunction(content, functionName) { + var indent = 0; + var splitter = "function " + functionName + "("; - return tools.loadMainJsAndIndex(mainJs, aliases, searchIndex, crate); + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = start; + while (pos < content.length && content[pos] !== ')') { + pos += 1; + } + if (pos >= content.length) { + break; + } + pos = getNextStep(content, pos + 1, '{'); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + // Eat single-line comments + if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') { + do { + pos += 1; + } while (pos < content.length && content[pos] !== '\n'); + + // Eat quoted strings + } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") { + var stop = content[pos]; + var is_escaped = false; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + + // Otherwise, check for indent + } else if (content[pos] === '{') { + indent += 1; + } else if (content[pos] === '}') { + indent -= 1; + if (indent === 0) { + return content.slice(start, pos + 1); + } + } + pos += 1; + } + content = content.slice(start + 1); + } + return null; } -function main(argv) { - if (argv.length < 4) { - console.error("USAGE: node tester.js OUT_FOLDER [TESTS]"); - return 1; +// Stupid function extractor for array. +function extractArrayVariable(content, arrayName) { + var splitter = "var " + arrayName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + pos = getNextStep(content, pos, '['); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ']' && + pos + 1 < content.length && + content[pos + 1] === ';') { + return content.slice(start, pos + 2); + } + pos += 1; + } + content = content.slice(start + 1); } - if (argv[2].substr(-1) !== "/") { - argv[2] += "/"; + return null; +} + +// Stupid function extractor for variable. +function extractVariable(content, varName) { + var splitter = "var " + varName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ';' || content[pos] === ',') { + return content.slice(start, pos + 1); + } + pos += 1; + } + content = content.slice(start + 1); } - const out_folder = argv[2]; + return null; +} +function loadContent(content) { + var Module = module.constructor; + var m = new Module(); + m._compile(content, "tmp.js"); + m.exports.ignore_order = content.indexOf("\n// ignore-order\n") !== -1 || + content.startsWith("// ignore-order\n"); + m.exports.exact_check = content.indexOf("\n// exact-check\n") !== -1 || + content.startsWith("// exact-check\n"); + m.exports.should_fail = content.indexOf("\n// should-fail\n") !== -1 || + content.startsWith("// should-fail\n"); + return m.exports; +} + +function readFile(filePath) { + return fs.readFileSync(filePath, 'utf8'); +} + +function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { + var content = ''; + for (var i = 0; i < thingsToLoad.length; ++i) { + var tmp = funcToCall(fileContent, thingsToLoad[i]); + if (tmp === null) { + console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); + process.exit(1); + } + content += tmp; + content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';'; + } + return content; +} + +function lookForEntry(entry, data) { + for (var i = 0; i < data.length; ++i) { + var allGood = true; + for (var key in entry) { + if (!entry.hasOwnProperty(key)) { + continue; + } + var value = data[i][key]; + // To make our life easier, if there is a "parent" type, we add it to the path. + if (key === 'path' && data[i]['parent'] !== undefined) { + if (value.length > 0) { + value += '::' + data[i]['parent']['name']; + } else { + value = data[i]['parent']['name']; + } + } + if (value !== entry[key]) { + allGood = false; + break; + } + } + if (allGood === true) { + return i; + } + } + return null; +} + +function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { + if (searchIndex[searchIndex.length - 1].length === 0) { + searchIndex.pop(); + } + searchIndex.pop(); + searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;'); + var finalJS = ""; + + var arraysToLoad = ["itemTypes"]; + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", + "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", + "TY_PRIMITIVE", "TY_KEYWORD", + "levenshtein_row2"]; + // execQuery first parameter is built in getQuery (which takes in the search input). + // execQuery last parameter is built in buildIndex. + // buildIndex requires the hashmap from search-index. + var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", + "getQuery", "buildIndex", "execQuery", "execSearch"]; + + finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; + finalJS += 'var rootPath = "../";\n'; + finalJS += aliases; + finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); + finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); + finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); + + var loaded = loadContent(finalJS); + var index = loaded.buildIndex(searchIndex.searchIndex); + + return [loaded, index]; +} + +function runChecks(testFile, loaded, index) { var errors = 0; + var loadedFile = loadContent( + readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); + + const expected = loadedFile.EXPECTED; + const query = loadedFile.QUERY; + const filter_crate = loadedFile.FILTER_CRATE; + const ignore_order = loadedFile.ignore_order; + const exact_check = loadedFile.exact_check; + const should_fail = loadedFile.should_fail; - for (var j = 3; j < argv.length; ++j) { - const test_file = argv[j]; - const test_name = path.basename(test_file, ".js"); + var results = loaded.execSearch(loaded.getQuery(query), index); + var error_text = []; - process.stdout.write('Checking "' + test_name + '" ... '); - if (!fs.existsSync(test_file)) { - errors += 1; - console.error("FAILED"); - console.error("==> Missing '" + test_name + ".js' file..."); + for (var key in expected) { + if (!expected.hasOwnProperty(key)) { continue; } + if (!results.hasOwnProperty(key)) { + error_text.push('==> Unknown key "' + key + '"'); + break; + } + var entry = expected[key]; + var prev_pos = -1; + for (var i = 0; i < entry.length; ++i) { + var entry_pos = lookForEntry(entry[i], results[key]); + if (entry_pos === null) { + error_text.push("==> Result not found in '" + key + "': '" + + JSON.stringify(entry[i]) + "'"); + } else if (exact_check === true && prev_pos + 1 !== entry_pos) { + error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " + + "expected '" + JSON.stringify(entry[i]) + "' but found '" + + JSON.stringify(results[key][i]) + "'"); + } else if (ignore_order === false && entry_pos < prev_pos) { + error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + + " before '" + JSON.stringify(results[key][entry_pos]) + "'"); + } else { + prev_pos = entry_pos; + } + } + } + if (error_text.length === 0 && should_fail === true) { + errors += 1; + console.error("FAILED"); + console.error("==> Test was supposed to fail but all items were found..."); + } else if (error_text.length !== 0 && should_fail === false) { + errors += 1; + console.error("FAILED"); + console.error(error_text.join("\n")); + } else { + console.log("OK"); + } + return errors; +} - const test_out_folder = out_folder + test_name; +function load_files(doc_folder, resource_suffix, crate) { + var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); + var aliases = readFile(path.join(doc_folder, "aliases" + resource_suffix + ".js")); + var searchIndex = readFile( + path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); + + return loadMainJsAndIndex(mainJs, aliases, searchIndex, crate); +} - var [loaded, index] = load_files(test_out_folder, test_name); - errors += tools.runChecks(test_file, loaded, index); +function showHelp() { + console.log("rustdoc-js options:"); + console.log(" --doc-folder [PATH] : location of the generated doc folder"); + console.log(" --help : show this message then quit"); + console.log(" --crate-name [STRING] : crate name to be used"); + console.log(" --test-file [PATH] : location of the JS test file"); + console.log(" --test-folder [PATH] : location of the JS tests folder"); + console.log(" --resource-suffix [STRING] : suffix to refer to the correct files"); +} + +function parseOptions(args) { + var opts = { + "crate_name": "", + "resource_suffix": "", + "doc_folder": "", + "test_folder": "", + "test_file": "", + }; + var correspondances = { + "--resource-suffix": "resource_suffix", + "--doc-folder": "doc_folder", + "--test-folder": "test_folder", + "--test-file": "test_file", + "--crate-name": "crate_name", + }; + + for (var i = 0; i < args.length; ++i) { + if (args[i] === "--resource-suffix" + || args[i] === "--doc-folder" + || args[i] === "--test-folder" + || args[i] === "--test-file" + || args[i] === "--crate-name") { + i += 1; + if (i >= args.length) { + console.error("Missing argument after `" + args[i - 1] + "` option."); + return null; + } + opts[correspondances[args[i - 1]]] = args[i]; + } else if (args[i] === "--help") { + showHelp(); + process.exit(0); + } else { + console.error("Unknown option `" + args[i] + "`."); + console.error("Use `--help` to see the list of options"); + return null; + } + } + if (opts["doc_folder"].length < 1) { + console.error("Missing `--doc-folder` option."); + } else if (opts["crate_name"].length < 1) { + console.error("Missing `--crate-name` option."); + } else if (opts["test_folder"].length < 1 && opts["test_file"].length < 1) { + console.error("At least one of `--test-folder` or `--test-file` option is required."); + } else { + return opts; + } + return null; +} + +function checkFile(test_file, opts, loaded, index) { + const test_name = path.basename(test_file, ".js"); + + process.stdout.write('Checking "' + test_name + '" ... '); + return runChecks(test_file, loaded, index); +} + +function main(argv) { + var opts = parseOptions(argv.slice(2)); + if (opts === null) { + return 1; + } + + var [loaded, index] = load_files( + opts["doc_folder"], + opts["resource_suffix"], + opts["crate_name"]); + var errors = 0; + + if (opts["test_file"].length !== 0) { + errors += checkFile(opts["test_file"], opts, loaded, index); + } + if (opts["test_folder"].length !== 0) { + fs.readdirSync(opts["test_folder"]).forEach(function(file) { + if (!file.endsWith(".js")) { + return; + } + errors += checkFile(path.join(opts["test_folder"], file), opts, loaded, index); + }); } return errors > 0 ? 1 : 0; }