diff --git a/Cargo.lock b/Cargo.lock index 3d0f9e8844e06..fbd823ad284dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4099,6 +4099,7 @@ dependencies = [ "rustc_hir", "rustc_middle", "rustc_span", + "rustc_target", "tracing", ] diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 69ccbf0b58ff3..0a1b639af5157 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -92,10 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.check_pat_top(¶m.pat, param_ty, ty_span, None); // Check that argument is Sized. - // The check for a non-trivial pattern is a hack to avoid duplicate warnings - // for simple cases like `fn foo(x: Trait)`, - // where we would error once on the parameter as a whole, and once on the binding `x`. - if param.pat.simple_ident().is_none() && !params_can_be_unsized { + if !params_can_be_unsized { fcx.require_type_is_sized( param_ty, param.pat.span, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 53ece08ac3d92..cbb4458d1d49a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3464,7 +3464,8 @@ declare_lint! { /// out an update in your own time. pub LONG_RUNNING_CONST_EVAL, Deny, - "detects long const eval operations" + "detects long const eval operations", + report_in_external_macro } declare_lint! { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c5a306fdf1f9a..c1d6856d33c92 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -318,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> { Ok(layout) => { return Ok(SizeSkeleton::Known(layout.size)); } - Err(err) => err, + Err(err @ LayoutError::Unknown(_)) => err, + // We can't extract SizeSkeleton info from other layout errors + Err( + e @ LayoutError::Cycle + | e @ LayoutError::SizeOverflow(_) + | e @ LayoutError::NormalizationFailure(..), + ) => return Err(e), }; match *ty.kind() { diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 80360a3c73f8d..5e271e6f871cf 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,13 +4,17 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_hir = { path = "../rustc_hir" } +# Use optional dependencies for rustc_* in order to support building this crate separately. +rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } +rustc_target = { path = "../rustc_target", optional = true } tracing = "0.1" [features] default = [ + "rustc_hir", "rustc_middle", "rustc_span", + "rustc_target", ] diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml index 157dfd620ee1b..d75e8e33b1c56 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/rustc_smir/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-02-28" +channel = "nightly-2023-06-14" components = [ "rustfmt", "rustc-dev" ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index b00f0a1c15312..4115694d5398c 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -13,6 +13,17 @@ #![cfg_attr(not(feature = "default"), feature(rustc_private))] #![feature(local_key_cell_methods)] #![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] // Used to define opaque types. + +// Declare extern rustc_* crates to enable building this crate separately from the compiler. +#[cfg(not(feature = "default"))] +extern crate rustc_hir; +#[cfg(not(feature = "default"))] +extern crate rustc_middle; +#[cfg(not(feature = "default"))] +extern crate rustc_span; +#[cfg(not(feature = "default"))] +extern crate rustc_target; pub mod rustc_internal; pub mod stable_mir; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 609a04d263c96..87e0b211556b9 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,6 +3,9 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. +use std::fmt::Debug; +use std::string::ToString; + use crate::{ rustc_smir::Tables, stable_mir::{self, with}, @@ -49,3 +52,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { crate::stable_mir::run(Tables { tcx, def_ids: vec![], types: vec![] }, f); } + +/// A type that provides internal information but that can still be used for debug purpose. +pub type Opaque = impl Debug + ToString + Clone; + +pub(crate) fn opaque(value: &T) -> Opaque { + format!("{value:?}") +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 874e34bef60f0..503de81d285db 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,10 +7,12 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. +use crate::rustc_internal::{self, opaque}; use crate::stable_mir::{self, ty::TyKind, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_target::abi::FieldIdx; use tracing::debug; impl<'tcx> Context for Tables<'tcx> { @@ -119,11 +121,21 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } } -pub trait Stable { +/// Trait used to convert between an internal MIR type to a Stable MIR type. +pub(crate) trait Stable { + /// The stable representation of the type implementing Stable. type T; + /// Converts an object to the equivalent Stable MIR representation. fn stable(&self) -> Self::T; } +impl Stable for DefId { + type T = stable_mir::CrateItem; + fn stable(&self) -> Self::T { + rustc_internal::crate_item(*self) + } +} + impl<'tcx> Stable for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self) -> Self::T { @@ -155,12 +167,18 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable()), Repeat(_, _) => todo!(), - Ref(_, _, _) => todo!(), - ThreadLocalRef(_) => todo!(), - AddressOf(_, _) => todo!(), - Len(_) => todo!(), + Ref(region, kind, place) => { + stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable()) + } + ThreadLocalRef(def_id) => stable_mir::mir::Rvalue::ThreadLocalRef(def_id.stable()), + AddressOf(mutability, place) => { + stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable()) + } + Len(place) => stable_mir::mir::Rvalue::Len(place.stable()), Cast(_, _, _) => todo!(), - BinaryOp(_, _) => todo!(), + BinaryOp(bin_op, ops) => { + stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable()) + } CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp( bin_op.stable(), ops.0.stable(), @@ -168,14 +186,108 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { ), NullaryOp(_, _) => todo!(), UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()), - Discriminant(_) => todo!(), + Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()), Aggregate(_, _) => todo!(), ShallowInitBox(_, _) => todo!(), - CopyForDeref(_) => todo!(), + CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()), + } + } +} + +impl Stable for mir::Mutability { + type T = stable_mir::mir::Mutability; + fn stable(&self) -> Self::T { + use mir::Mutability::*; + match *self { + Not => stable_mir::mir::Mutability::Not, + Mut => stable_mir::mir::Mutability::Mut, + } + } +} + +impl Stable for mir::BorrowKind { + type T = stable_mir::mir::BorrowKind; + fn stable(&self) -> Self::T { + use mir::BorrowKind::*; + match *self { + Shared => stable_mir::mir::BorrowKind::Shared, + Shallow => stable_mir::mir::BorrowKind::Shallow, + Unique => stable_mir::mir::BorrowKind::Unique, + Mut { allow_two_phase_borrow } => { + stable_mir::mir::BorrowKind::Mut { allow_two_phase_borrow } + } + } + } +} + +impl<'tcx> Stable for mir::NullOp<'tcx> { + type T = stable_mir::mir::NullOp; + fn stable(&self) -> Self::T { + use mir::NullOp::*; + match self { + SizeOf => stable_mir::mir::NullOp::SizeOf, + AlignOf => stable_mir::mir::NullOp::AlignOf, + OffsetOf(indices) => { + stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect()) + } + } + } +} + +impl Stable for mir::CastKind { + type T = stable_mir::mir::CastKind; + fn stable(&self) -> Self::T { + use mir::CastKind::*; + match self { + PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress, + PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress, + Pointer(cast) => stable_mir::mir::CastKind::Pointer(cast.stable()), + DynStar => stable_mir::mir::CastKind::DynStar, + IntToInt => stable_mir::mir::CastKind::IntToInt, + FloatToInt => stable_mir::mir::CastKind::FloatToInt, + FloatToFloat => stable_mir::mir::CastKind::FloatToFloat, + IntToFloat => stable_mir::mir::CastKind::IntToFloat, + PtrToPtr => stable_mir::mir::CastKind::PtrToPtr, + FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr, + Transmute => stable_mir::mir::CastKind::Transmute, + } + } +} + +impl Stable for ty::adjustment::PointerCast { + type T = stable_mir::mir::PointerCast; + fn stable(&self) -> Self::T { + use ty::adjustment::PointerCast; + match self { + PointerCast::ReifyFnPointer => stable_mir::mir::PointerCast::ReifyFnPointer, + PointerCast::UnsafeFnPointer => stable_mir::mir::PointerCast::UnsafeFnPointer, + PointerCast::ClosureFnPointer(unsafety) => { + stable_mir::mir::PointerCast::ClosureFnPointer(unsafety.stable()) + } + PointerCast::MutToConstPointer => stable_mir::mir::PointerCast::MutToConstPointer, + PointerCast::ArrayToPointer => stable_mir::mir::PointerCast::ArrayToPointer, + PointerCast::Unsize => stable_mir::mir::PointerCast::Unsize, + } + } +} + +impl Stable for rustc_hir::Unsafety { + type T = stable_mir::mir::Safety; + fn stable(&self) -> Self::T { + match self { + rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe, + rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal, } } } +impl Stable for FieldIdx { + type T = usize; + fn stable(&self) -> Self::T { + self.as_usize() + } +} + impl<'tcx> Stable for mir::Operand<'tcx> { type T = stable_mir::mir::Operand; fn stable(&self) -> Self::T { @@ -211,34 +323,38 @@ impl Stable for mir::UnwindAction { } } -fn rustc_assert_msg_to_msg<'tcx>( - assert_message: &rustc_middle::mir::AssertMessage<'tcx>, -) -> stable_mir::mir::AssertMessage { - use rustc_middle::mir::AssertKind; - match assert_message { - AssertKind::BoundsCheck { len, index } => { - stable_mir::mir::AssertMessage::BoundsCheck { len: len.stable(), index: index.stable() } - } - AssertKind::Overflow(bin_op, op1, op2) => { - stable_mir::mir::AssertMessage::Overflow(bin_op.stable(), op1.stable(), op2.stable()) - } - AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), - AssertKind::DivisionByZero(op) => { - stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) - } - AssertKind::RemainderByZero(op) => { - stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) - } - AssertKind::ResumedAfterReturn(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) - } - AssertKind::ResumedAfterPanic(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) - } - AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { - required: required.stable(), - found: found.stable(), +impl<'tcx> Stable for mir::AssertMessage<'tcx> { + type T = stable_mir::mir::AssertMessage; + fn stable(&self) -> Self::T { + use rustc_middle::mir::AssertKind; + match self { + AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck { + len: len.stable(), + index: index.stable(), + }, + AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow( + bin_op.stable(), + op1.stable(), + op2.stable(), + ), + AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), + AssertKind::DivisionByZero(op) => { + stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) + } + AssertKind::RemainderByZero(op) => { + stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) + } + AssertKind::ResumedAfterReturn(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) + } + AssertKind::ResumedAfterPanic(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) + } + AssertKind::MisalignedPointerDereference { required, found } => { + stable_mir::mir::AssertMessage::MisalignedPointerDereference { + required: required.stable(), + found: found.stable(), + } } } } @@ -363,7 +479,7 @@ impl<'tcx> Stable for mir::Terminator<'tcx> { Assert { cond, expected, msg, target, unwind } => Terminator::Assert { cond: cond.stable(), expected: *expected, - msg: rustc_assert_msg_to_msg(msg), + msg: msg.stable(), target: target.as_usize(), unwind: unwind.stable(), }, diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 468e915d1a073..a0b69d6cf780a 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,4 +1,5 @@ -use crate::stable_mir::ty::Ty; +use crate::rustc_internal::Opaque; +use crate::stable_mir::{self, ty::Ty}; #[derive(Clone, Debug)] pub struct Body { @@ -136,12 +137,98 @@ pub enum Statement { Nop, } +type Region = Opaque; + // FIXME this is incomplete #[derive(Clone, Debug)] pub enum Rvalue { - Use(Operand), + /// Creates a pointer with the indicated mutability to the place. + /// + /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like + /// `&raw v` or `addr_of!(v)`. + AddressOf(Mutability, Place), + + /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second + /// parameter may be a `usize` as well. + /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, + /// raw pointers, or function pointers and return a `bool`. The types of the operands must be + /// matching, up to the usual caveat of the lifetimes in function pointers. + /// * Left and right shift operations accept signed or unsigned integers not necessarily of the + /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is + /// truncated as needed. + /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching + /// types and return a value of that type. + /// * The remaining operations accept signed integers, unsigned integers, or floats with + /// matching types and return a value of that type. + BinaryOp(BinOp, Operand, Operand), + + /// Performs essentially all of the casts that can be performed via `as`. + /// + /// This allows for casts from/to a variety of types. + Cast(CastKind, Operand, Ty), + + /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. + /// + /// For addition, subtraction, and multiplication on integers the error condition is set when + /// the infinite precision result would not be equal to the actual result. CheckedBinaryOp(BinOp, Operand, Operand), + + /// A CopyForDeref is equivalent to a read from a place. + /// When such a read happens, it is guaranteed that the only use of the returned value is a + /// deref operation, immediately followed by one or more projections. + CopyForDeref(Place), + + /// Computes the discriminant of the place, returning it as an integer of type + /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// + /// The validity requirements for the underlying value are undecided for this rvalue, see + /// [#91095]. Note too that the value of the discriminant is not the same thing as the + /// variant index; use [`discriminant_for_variant`] to convert. + /// + /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty + /// [#91095]: https://github.com/rust-lang/rust/issues/91095 + /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant + Discriminant(Place), + + /// Yields the length of the place, as a `usize`. + /// + /// If the type of the place is an array, this is the array length. For slices (`[T]`, not + /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is + /// ill-formed for places of other types. + Len(Place), + + /// Creates a reference to the place. + Ref(Region, BorrowKind, Place), + + /// Transmutes a `*mut u8` into shallow-initialized `Box`. + /// + /// This is different from a normal transmute because dataflow analysis will treat the box as + /// initialized but its content as uninitialized. Like other pointer casts, this in general + /// affects alias analysis. + ShallowInitBox(Operand, Ty), + + /// Creates a pointer/reference to the given thread local. + /// + /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a + /// `*const T`, and if neither of those apply a `&T`. + /// + /// **Note:** This is a runtime operation that actually executes code and is in this sense more + /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to + /// SIGILL for some reason that I (JakobDegen) never got a chance to look into. + /// + /// **Needs clarification**: Are there weird additional semantics here related to the runtime + /// nature of this operation? + ThreadLocalRef(stable_mir::CrateItem), + + /// Exactly like `BinaryOp`, but less operands. + /// + /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; + /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds + /// return a value with the same type as their operand. UnaryOp(UnOp, Operand), + + /// Yields the operand unchanged + Use(Operand), } #[derive(Clone, Debug)] @@ -157,8 +244,97 @@ pub struct Place { pub projection: String, } +type FieldIdx = usize; + #[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, pub target: usize, } + +#[derive(Clone, Debug)] +pub enum BorrowKind { + /// Data must be immutable and is aliasable. + Shared, + + /// The immediately borrowed place must be immutable, but projections from + /// it don't need to be. For example, a shallow borrow of `a.b` doesn't + /// conflict with a mutable borrow of `a.b.c`. + Shallow, + + /// Data must be immutable but not aliasable. This kind of borrow + /// cannot currently be expressed by the user and is used only in + /// implicit closure bindings. It is needed when the closure is + /// borrowing or mutating a mutable referent. + Unique, + + /// Data is mutable and not aliasable. + Mut { + /// `true` if this borrow arose from method-call auto-ref + allow_two_phase_borrow: bool, + }, +} + +#[derive(Clone, Debug)] +pub enum Mutability { + Not, + Mut, +} + +#[derive(Clone, Debug)] +pub enum Safety { + Unsafe, + Normal, +} + +#[derive(Clone, Debug)] +pub enum PointerCast { + /// Go from a fn-item type to a fn-pointer type. + ReifyFnPointer, + + /// Go from a safe fn pointer to an unsafe fn pointer. + UnsafeFnPointer, + + /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer. + /// It cannot convert a closure that requires unsafe. + ClosureFnPointer(Safety), + + /// Go from a mut raw pointer to a const raw pointer. + MutToConstPointer, + + /// Go from `*const [T; N]` to `*const T` + ArrayToPointer, + + /// Unsize a pointer/reference value, e.g., `&[T; n]` to + /// `&[T]`. Note that the source could be a thin or fat pointer. + /// This will do things like convert thin pointers to fat + /// pointers, or convert structs containing thin pointers to + /// structs containing fat pointers, or convert between fat + /// pointers. + Unsize, +} + +#[derive(Clone, Debug)] +pub enum CastKind { + PointerExposeAddress, + PointerFromExposedAddress, + Pointer(PointerCast), + DynStar, + IntToInt, + FloatToInt, + FloatToFloat, + IntToFloat, + PtrToPtr, + FnPtrToPtr, + Transmute, +} + +#[derive(Clone, Debug)] +pub enum NullOp { + /// Returns the size of a value of that type. + SizeOf, + /// Returns the minimum alignment of a type. + AlignOf, + /// Returns the offset of a field. + OffsetOf(Vec), +} diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f48bba241327e..c8c2c8286b04f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -145,17 +145,35 @@ fn layout_of_uncached<'tcx>( return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } - let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() // Projection eagerly bails out when the pointee references errors, // fall back to structurally deducing metadata. && !pointee.references_error() { - let metadata_ty = tcx.normalize_erasing_regions( + let pointee_metadata = tcx.mk_projection(metadata_def_id, [pointee]); + let metadata_ty = match tcx.try_normalize_erasing_regions( param_env, - tcx.mk_projection(metadata_def_id, [pointee]), - ); + pointee_metadata, + ) { + Ok(metadata_ty) => metadata_ty, + Err(mut err) => { + // Usually `::Metadata` can't be normalized because + // its struct tail cannot be normalized either, so try to get a + // more descriptive layout error here, which will lead to less confusing + // diagnostics. + match tcx.try_normalize_erasing_regions( + param_env, + tcx.struct_tail_without_normalization(pointee), + ) { + Ok(_) => {}, + Err(better_err) => { + err = better_err; + } + } + return Err(LayoutError::NormalizationFailure(pointee, err)); + }, + }; + let metadata_layout = cx.layout_of(metadata_ty)?; // If the metadata is a 1-zst, then the pointer is thin. if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { @@ -163,10 +181,13 @@ fn layout_of_uncached<'tcx>( } let Abi::Scalar(metadata) = metadata_layout.abi else { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); }; + metadata } else { + let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + match unsized_part.kind() { ty::Foreign(..) => { return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); @@ -178,7 +199,7 @@ fn layout_of_uncached<'tcx>( vtable } _ => { - return Err(LayoutError::Unknown(unsized_part)); + return Err(LayoutError::Unknown(pointee)); } } }; diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 06f479808b975..cb40521dda763 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -54,9 +54,9 @@ impl Config { /// Runs a command, printing out nice contextual information if it fails. /// Exits if the command failed to execute at all, otherwise returns its /// `status.success()`. - pub(crate) fn try_run(&self, cmd: &mut Command) -> bool { + pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> { if self.dry_run() { - return true; + return Ok(()); } self.verbose(&format!("running: {:?}", cmd)); try_run(cmd, self.is_verbose()) @@ -156,12 +156,14 @@ impl Config { ]; } "; - nix_build_succeeded = self.try_run(Command::new("nix-build").args(&[ - Path::new("-E"), - Path::new(NIX_EXPR), - Path::new("-o"), - &nix_deps_dir, - ])); + nix_build_succeeded = self + .try_run(Command::new("nix-build").args(&[ + Path::new("-E"), + Path::new(NIX_EXPR), + Path::new("-o"), + &nix_deps_dir, + ])) + .is_ok(); nix_deps_dir }); if !nix_build_succeeded { @@ -186,7 +188,7 @@ impl Config { patchelf.args(&["--set-interpreter", dynamic_linker.trim_end()]); } - self.try_run(patchelf.arg(fname)); + self.try_run(patchelf.arg(fname)).unwrap(); } fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { @@ -237,7 +239,7 @@ impl Config { "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", url, tempfile.to_str().expect("invalid UTF-8 not supported with powershell downloads"), ), - ])) { + ])).is_err() { return; } eprintln!("\nspurious failure, trying again"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d7e77aeb338f6..d389b568f563d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -333,7 +333,7 @@ forward! { create(path: &Path, s: &str), remove(f: &Path), tempdir() -> PathBuf, - try_run(cmd: &mut Command) -> bool, + try_run(cmd: &mut Command) -> Result<(), ()>, llvm_link_shared() -> bool, download_rustc() -> bool, initial_rustfmt() -> Option, @@ -614,11 +614,13 @@ impl Build { } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). - let has_local_modifications = !self.try_run( - Command::new("git") - .args(&["diff-index", "--quiet", "HEAD"]) - .current_dir(&absolute_path), - ); + let has_local_modifications = self + .try_run( + Command::new("git") + .args(&["diff-index", "--quiet", "HEAD"]) + .current_dir(&absolute_path), + ) + .is_err(); if has_local_modifications { self.run(Command::new("git").args(&["stash", "push"]).current_dir(&absolute_path)); } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index ec01f744b8250..c97b759273717 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -27,7 +27,8 @@ impl Step for ExpandYamlAnchors { try_run( builder, &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("generate").arg(&builder.src), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -39,17 +40,17 @@ impl Step for ExpandYamlAnchors { } } -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { +fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { if !builder.fail_fast { - if !builder.try_run(cmd) { + if let Err(e) = builder.try_run(cmd) { let mut failures = builder.delayed_failures.borrow_mut(); failures.push(format!("{:?}", cmd)); - return false; + return Err(e); } } else { builder.run(cmd); } - true + Ok(()) } #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9212362f6c9e1..873ed61daf33c 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -48,17 +48,17 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ // build for, so there is no entry for "aarch64-apple-darwin" here. ]; -fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { +fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> Result<(), ()> { if !builder.fail_fast { - if !builder.try_run(cmd) { + if let Err(e) = builder.try_run(cmd) { let mut failures = builder.delayed_failures.borrow_mut(); failures.push(format!("{:?}", cmd)); - return false; + return Err(e); } } else { builder.run(cmd); } - true + Ok(()) } fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool { @@ -187,7 +187,8 @@ You can skip linkcheck with --exclude src/tools/linkchecker" try_run( builder, builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -240,7 +241,8 @@ impl Step for HtmlCheck { builder.default_doc(&[]); builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder)); - try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))); + try_run(builder, builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target))) + .unwrap(); } } @@ -286,7 +288,8 @@ impl Step for Cargotest { .args(builder.config.test_args()) .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)), - ); + ) + .unwrap(); } } @@ -785,7 +788,7 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder, compiler); let mut cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder); - if builder.try_run(&mut cargo) { + if builder.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. return; } @@ -858,7 +861,7 @@ impl Step for RustdocTheme { util::lld_flag_no_threads(self.compiler.host.contains("windows")), ); } - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); } } @@ -1109,7 +1112,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` } builder.info("tidy check"); - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); builder.ensure(ExpandYamlAnchors); @@ -1157,7 +1160,8 @@ impl Step for ExpandYamlAnchors { try_run( builder, &mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src), - ); + ) + .unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -1936,7 +1940,7 @@ impl BookTest { compiler.host, ); let _time = util::timeit(&builder); - let toolstate = if try_run(builder, &mut rustbook_cmd) { + let toolstate = if try_run(builder, &mut rustbook_cmd).is_ok() { ToolState::TestPass } else { ToolState::TestFail @@ -2094,7 +2098,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> cmd.arg("--test-args").arg(test_args); if builder.config.verbose_tests { - try_run(builder, &mut cmd) + try_run(builder, &mut cmd).is_ok() } else { try_run_quiet(builder, &mut cmd) } @@ -2122,7 +2126,7 @@ impl Step for RustcGuide { let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)) { + let toolstate = if try_run(builder, rustbook_cmd.arg("linkcheck").arg(&src)).is_ok() { ToolState::TestPass } else { ToolState::TestFail @@ -2661,7 +2665,7 @@ impl Step for Bootstrap { fn run(self, builder: &Builder<'_>) { let mut check_bootstrap = Command::new(&builder.python()); check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/")); - try_run(builder, &mut check_bootstrap); + try_run(builder, &mut check_bootstrap).unwrap(); let host = builder.config.build; let compiler = builder.compiler(0, host); @@ -2733,7 +2737,7 @@ impl Step for TierCheck { } builder.info("platform support check"); - try_run(builder, &mut cargo.into()); + try_run(builder, &mut cargo.into()).unwrap(); } } @@ -2813,7 +2817,7 @@ impl Step for RustInstaller { cmd.env("CARGO", &builder.initial_cargo); cmd.env("RUSTC", &builder.initial_rustc); cmd.env("TMP_DIR", &tmpdir); - try_run(builder, &mut cmd); + try_run(builder, &mut cmd).unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 96341b69df046..126f0b1eb31a4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -107,7 +107,7 @@ impl Step for ToolBuild { ); let mut cargo = Command::from(cargo); - let is_expected = builder.try_run(&mut cargo); + let is_expected = builder.try_run(&mut cargo).is_ok(); builder.save_toolstate( tool, diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 1ec49f80d632e..b291584b300ce 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -228,7 +228,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( } pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) { - if !try_run(cmd, print_cmd_on_fail) { + if try_run(cmd, print_cmd_on_fail).is_err() { crate::detail_exit_macro!(1); } } diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index eade9e0455912..5ab1874e9ed46 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -110,6 +110,9 @@ * `@has-dir PATH` checks for the existence of the given directory. +* `@files FOLDER_PATH [ENTRIES]`, checks that `FOLDER_PATH` contains exactly + `[ENTRIES]`. + All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` checks if the given file does not exist, for example. @@ -321,12 +324,15 @@ def resolve_path(self, path): else: return self.last_path + def get_absolute_path(self, path): + return os.path.join(self.root, path) + def get_file(self, path): path = self.resolve_path(path) if path in self.files: return self.files[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -340,7 +346,7 @@ def get_tree(self, path): if path in self.trees: return self.trees[path] - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isfile(abspath)): raise FailedCheck('File does not exist {!r}'.format(path)) @@ -356,7 +362,7 @@ def get_tree(self, path): def get_dir(self, path): path = self.resolve_path(path) - abspath = os.path.join(self.root, path) + abspath = self.get_absolute_path(path) if not(os.path.exists(abspath) and os.path.isdir(abspath)): raise FailedCheck('Directory does not exist {!r}'.format(path)) @@ -538,6 +544,41 @@ def get_nb_matching_elements(cache, c, regexp, stop_at_first): return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first) +def check_files_in_folder(c, cache, folder, files): + files = files.strip() + if not files.startswith('[') or not files.endswith(']'): + raise InvalidCheck("Expected list as second argument of @{} (ie '[]')".format(c.cmd)) + + folder = cache.get_absolute_path(folder) + + # First we create a set of files to check if there are duplicates. + files = shlex.split(files[1:-1].replace(",", "")) + files_set = set() + for file in files: + if file in files_set: + raise InvalidCheck("Duplicated file `{}` in @{}".format(file, c.cmd)) + files_set.add(file) + folder_set = set([f for f in os.listdir(folder) if f != "." and f != ".."]) + + # Then we remove entries from both sets (we clone `folder_set` so we can iterate it while + # removing its elements). + for entry in set(folder_set): + if entry in files_set: + files_set.remove(entry) + folder_set.remove(entry) + + error = 0 + if len(files_set) != 0: + print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format( + folder, files_set)) + error += 1 + if len(folder_set) != 0: + print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format( + folder, folder_set)) + error += 1 + return error == 0 + + ERR_COUNT = 0 @@ -566,6 +607,13 @@ def check_command(c, cache): else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + elif c.cmd == 'files': # check files in given folder + if len(c.args) != 2: # @files + raise InvalidCheck("Invalid number of @{} arguments".format(c.cmd)) + elif c.negated: + raise InvalidCheck("@{} doesn't support negative check".format(c.cmd)) + ret = check_files_in_folder(c, cache, c.args[0], c.args[1]) + elif c.cmd == 'count': # count test if len(c.args) == 3: # @count = count test expected = int(c.args[2]) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 294de12cea8e2..f375f0efbd17b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::Write as _; use std::mem; +use std::sync::LazyLock as Lazy; use thin_vec::{thin_vec, ThinVec}; #[cfg(test)] @@ -582,6 +583,8 @@ pub(crate) fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { /// /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); +pub(crate) static DOC_CHANNEL: Lazy<&'static str> = + Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit("/").filter(|c| !c.is_empty()).next().unwrap()); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 6ab849c92a076..8c5871d912647 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -55,6 +55,7 @@ struct PageLayout<'a> { sidebar: String, content: String, krate_with_trailing_slash: String, + rust_channel: &'static str, pub(crate) rustdoc_version: &'a str, } @@ -82,6 +83,7 @@ pub(crate) fn render( sidebar, content, krate_with_trailing_slash, + rust_channel: *crate::clean::utils::DOC_CHANNEL, rustdoc_version, } .render() diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f5296abaee661..254b0d8bf5a43 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1050,9 +1050,10 @@ function preLoadCss(cssUrl) { function buildHelpMenu() { const book_info = document.createElement("span"); + const channel = getVar("channel"); book_info.className = "top"; - book_info.innerHTML = "You can find more information in \ - the rustdoc book."; + book_info.innerHTML = `You can find more information in \ +the rustdoc book.`; const shortcuts = [ ["?", "Show this help dialog"], @@ -1072,6 +1073,9 @@ function preLoadCss(cssUrl) { div_shortcuts.innerHTML = "

Keyboard Shortcuts

" + shortcuts + "
"; const infos = [ + `For a full list of all search features, take a look here.`, "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 9133f899af60d..759c4fd601226 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -31,6 +31,7 @@ data-themes="{{themes|join(",") }}" {#+ #} data-resource-suffix="{{page.resource_suffix}}" {#+ #} data-rustdoc-version="{{rustdoc_version}}" {#+ #} + data-channel="{{rust_channel}}" {#+ #} data-search-js="{{files.search_js}}" {#+ #} data-settings-js="{{files.settings_js}}" {#+ #} data-settings-css="{{files.settings_css}}" {#+ #} diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs index 731095023a96e..11b8a228b8a8e 100644 --- a/src/tools/build_helper/src/util.rs +++ b/src/tools/build_helper/src/util.rs @@ -25,17 +25,21 @@ pub fn fail(s: &str) -> ! { detail_exit(1, cfg!(test)); } -pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool { +pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> { let status = match cmd.status() { Ok(status) => status, Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)), }; - if !status.success() && print_cmd_on_fail { - println!( - "\n\ncommand did not execute successfully: {:?}\n\ - expected success, got: {}\n\n", - cmd, status - ); + if !status.success() { + if print_cmd_on_fail { + println!( + "\n\ncommand did not execute successfully: {:?}\n\ + expected success, got: {}\n\n", + cmd, status + ); + } + Err(()) + } else { + Ok(()) } - status.success() } diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index dc902f8cb0242..0ddd2c66cf9ea 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -67,7 +67,7 @@ fn find_librs>(path: P) -> Option { None } -fn main() { +fn main() -> Result<(), ()> { let config = Arc::new(Config::from_args(env::args().collect())); // The goal here is to check if the necessary packages are installed, and if not, we @@ -128,7 +128,10 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse } } - try_run(&mut cargo, config.verbose); + if try_run(&mut cargo, config.verbose).is_err() { + eprintln!("failed to document `{}`", entry.path().display()); + panic!("Cannot run rustdoc-gui tests"); + } } } @@ -158,5 +161,5 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse command.args(&config.test_args); - try_run(&mut command, config.verbose); + try_run(&mut command, config.verbose) } diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 193a3eb3fd134..e3c628b366fbd 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -31,7 +31,7 @@ define-function: ( // color of the typename (struct, module, method, ...) before search results assert-css: ( ".result-name .typename", - {"color": "#888"}, + {"color": |grey|}, ALL, ) }, @@ -75,6 +75,7 @@ store-value: (entry_color, "#0096cf") // color of the search entry store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#3c3c3c") // hover background color +store-value: (grey, "#999") call-function: ( "check-result-color", ( @@ -186,6 +187,7 @@ store-value: (entry_color, "#ddd") // color of the search entry store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#616161") // hover background color +store-value: (grey, "#ccc") call-function: ( "check-result-color", ( @@ -282,6 +284,7 @@ store-value: (entry_color, "#000") // color of the search entry store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color store-value: (hover_background_color, "#ccc") // hover background color +store-value: (grey, "#999") call-function: ( "check-result-color", ( diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs index bcabbfc91e869..498d9cdaef1f0 100644 --- a/tests/rustdoc/files-creation-hidden.rs +++ b/tests/rustdoc/files-creation-hidden.rs @@ -1,5 +1,6 @@ #![crate_name="foo"] +// @files foo '["index.html", "all.html", "sidebar-items.js"]' // @!has "foo/struct.Foo.html" #[doc(hidden)] pub struct Foo; diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/files-creation-private.rs index ca2327e0f911a..e2fdbc068f8aa 100644 --- a/tests/rustdoc/files-creation-private.rs +++ b/tests/rustdoc/files-creation-private.rs @@ -1,5 +1,9 @@ #![crate_name="foo"] +// @files "foo" \ +// '["index.html", "all.html", "sidebar-items.js", "foo", "bar", "private", "struct.Bar.html"]' +// @files "foo/bar" '["index.html", "sidebar-items.js"]' + // @!has "foo/priv/index.html" // @!has "foo/priv/struct.Foo.html" mod private { diff --git a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs index d6832bb7a0977..65c26d6a83751 100644 --- a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs +++ b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs @@ -2,6 +2,12 @@ #![no_core] #![crate_name = "foo"] +// @files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \ +// 'visible']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" +// @files "foo/visible" "['index.html', 'sidebar-items.js', 'trait.Foo.html']" + // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html' // FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249 diff --git a/tests/rustdoc/issue-111249-file-creation.rs b/tests/rustdoc/issue-111249-file-creation.rs index d2042b231e469..afd65ddaf941f 100644 --- a/tests/rustdoc/issue-111249-file-creation.rs +++ b/tests/rustdoc/issue-111249-file-creation.rs @@ -2,6 +2,12 @@ #![feature(no_core)] #![no_core] +// @files "foo" "['all.html', 'visible', 'index.html', 'sidebar-items.js', 'hidden', \ +// 'struct.Bar.html']" +// @files "foo/visible" "['trait.Foo.html', 'index.html', 'sidebar-items.js']" +// @files "foo/hidden" "['inner']" +// @files "foo/hidden/inner" "['trait.Foo.html']" + // The following five should not fail! // @!has 'foo/hidden/index.html' // @!has 'foo/hidden/inner/index.html' diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs new file mode 100644 index 0000000000000..2d8565517e897 --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.rs @@ -0,0 +1,11 @@ +#![feature(unsized_fn_params)] + +fn main() { + // CoerceMany "LUB" + let f = if true { |_a| {} } else { |_b| {} }; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| ERROR the size for values of type `[u8]` cannot be known at compilation time + + let slice: Box<[u8]> = Box::new([1; 8]); + f(*slice); +} diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr new file mode 100644 index 0000000000000..d88b84365dfae --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:24 + | +LL | let f = if true { |_a| {} } else { |_b| {} }; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr-2.rs:5:41 + | +LL | let f = if true { |_a| {} } else { |_b| {} }; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.rs b/tests/ui/closures/cannot-call-unsized-via-ptr.rs new file mode 100644 index 0000000000000..5ce4650b0333c --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr.rs @@ -0,0 +1,10 @@ +#![feature(unsized_fn_params)] + +fn main() { + // Simple coercion + let f: fn([u8]) = |_result| {}; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + + let slice: Box<[u8]> = Box::new([1; 8]); + f(*slice); +} diff --git a/tests/ui/closures/cannot-call-unsized-via-ptr.stderr b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr new file mode 100644 index 0000000000000..9ecc66d5ce897 --- /dev/null +++ b/tests/ui/closures/cannot-call-unsized-via-ptr.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cannot-call-unsized-via-ptr.rs:5:24 + | +LL | let f: fn([u8]) = |_result| {}; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr index 0432f2fa8be5d..bd8a4feeff5e7 100644 --- a/tests/ui/const-generics/issue-112505-overflow.stderr +++ b/tests/ui/const-generics/issue-112505-overflow.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | unsafe { std::mem::transmute(v) } | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (59484438436515561504 bits) + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error: aborting due to previous error diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 3d1197afd0f79..9e308620a9c2e 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -43,8 +43,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture) + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error: aborting due to 6 previous errors diff --git a/tests/ui/consts/timeout.rs b/tests/ui/consts/timeout.rs new file mode 100644 index 0000000000000..c9094999ee276 --- /dev/null +++ b/tests/ui/consts/timeout.rs @@ -0,0 +1,25 @@ +//! This test checks that external macros don't hide +//! the const eval timeout lint and then subsequently +//! ICE. + +// compile-flags: --crate-type=lib -Ztiny-const-eval-limit +// error-pattern: constant evaluation is taking a long time + +static ROOK_ATTACKS_TABLE: () = { + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); + 0_u64.count_ones(); +}; diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr new file mode 100644 index 0000000000000..799b5ec8dd9f1 --- /dev/null +++ b/tests/ui/consts/timeout.stderr @@ -0,0 +1,15 @@ +error: constant evaluation is taking a long time + --> $SRC_DIR/core/src/num/mod.rs:LL:COL + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/timeout.rs:8:1 + | +LL | static ROOK_ATTACKS_TABLE: () = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + = note: this error originates in the macro `uint_impl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs index 82866b355573c..f9dd2c54d997f 100644 --- a/tests/ui/issues/issue-5883.rs +++ b/tests/ui/issues/issue-5883.rs @@ -6,7 +6,7 @@ struct Struct { fn new_struct( r: dyn A + 'static //~ ERROR the size for values of type -) -> Struct { //~ ERROR the size for values of type +) -> Struct { Struct { r: r } } diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr index ffff403e0d465..a3e2531b5caa4 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/issues/issue-5883.stderr @@ -15,22 +15,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | r: &dyn A + 'static | + -error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:9:6 - | -LL | ) -> Struct { - | ^^^^^^ doesn't have a size known at compile-time -LL | Struct { r: r } - | --------------- this returned value is of type `Struct` - | - = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` -note: required because it appears within the type `Struct` - --> $DIR/issue-5883.rs:3:8 - | -LL | struct Struct { - | ^^^^^^ - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.rs b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs new file mode 100644 index 0000000000000..d2b6e1d8eba66 --- /dev/null +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.rs @@ -0,0 +1,22 @@ +trait Trait { + type RefTarget; +} + +impl Trait for () +where + Missing: Trait, + //~^ ERROR cannot find type `Missing` in this scope +{ + type RefTarget = (); +} + +struct Other { + data: <() as Trait>::RefTarget, +} + +fn main() { + unsafe { + std::mem::transmute::, Option<&Other>>(None); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types + } +} diff --git a/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr new file mode 100644 index 0000000000000..dd5119318ff4b --- /dev/null +++ b/tests/ui/layout/cannot-transmute-unnormalizable-type.stderr @@ -0,0 +1,19 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/cannot-transmute-unnormalizable-type.rs:7:5 + | +LL | Missing: Trait, + | ^^^^^^^ not found in this scope + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/cannot-transmute-unnormalizable-type.rs:19:9 + | +LL | std::mem::transmute::, Option<&Other>>(None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<()>` (8 bits) + = note: target type: `Option<&Other>` (unable to determine layout for `Other` because `<() as Trait>::RefTarget` cannot be normalized) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0512. +For more information about an error, try `rustc --explain E0412`.