From 414ebeaeea13d37bcd59473d11660169286b7cd5 Mon Sep 17 00:00:00 2001 From: Stephen Skeirik Date: Mon, 17 Jun 2024 17:01:38 -0400 Subject: [PATCH 01/49] add serde derive Serialize to stable_mir --- Cargo.lock | 1 + compiler/stable_mir/Cargo.toml | 1 + compiler/stable_mir/src/abi.rs | 35 ++--- compiler/stable_mir/src/crate_def.rs | 3 +- compiler/stable_mir/src/lib.rs | 10 +- compiler/stable_mir/src/mir/alloc.rs | 5 +- compiler/stable_mir/src/mir/body.rs | 81 +++++------ compiler/stable_mir/src/mir/mono.rs | 10 +- compiler/stable_mir/src/target.rs | 7 +- compiler/stable_mir/src/ty.rs | 153 ++++++++++++--------- tests/ui-fulldeps/stable-mir/smir_serde.rs | 75 ++++++++++ 11 files changed, 242 insertions(+), 139 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/smir_serde.rs diff --git a/Cargo.lock b/Cargo.lock index 241a37588b40..24caf5cd3e67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5254,6 +5254,7 @@ name = "stable_mir" version = "0.1.0-preview" dependencies = [ "scoped-tls", + "serde", ] [[package]] diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml index 4ed611527365..2edb3f140d7a 100644 --- a/compiler/stable_mir/Cargo.toml +++ b/compiler/stable_mir/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] scoped-tls = "1.0" +serde = { version = "1.0.125", features = [ "derive" ] } diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index e1c14fe0b380..c003ec1fbc92 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -5,12 +5,13 @@ use crate::target::{MachineInfo, MachineSize as Size}; use crate::ty::{Align, IndexedVal, Ty, VariantIdx}; use crate::Error; use crate::Opaque; +use serde::Serialize; use std::fmt::{self, Debug}; use std::num::NonZero; use std::ops::RangeInclusive; /// A function ABI definition. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct FnAbi { /// The types of each argument. pub args: Vec, @@ -31,7 +32,7 @@ pub struct FnAbi { } /// Information about the ABI of a function's argument, or return value. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct ArgAbi { pub ty: Ty, pub layout: Layout, @@ -39,7 +40,7 @@ pub struct ArgAbi { } /// How a function argument should be passed in to the target function. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum PassMode { /// Ignore the argument. /// @@ -60,14 +61,14 @@ pub enum PassMode { } /// The layout of a type, alongside the type itself. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct TyAndLayout { pub ty: Ty, pub layout: Layout, } /// The layout of a type in memory. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct LayoutShape { /// The fields location withing the layout pub fields: FieldsShape, @@ -108,7 +109,7 @@ impl LayoutShape { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct Layout(usize); impl Layout { @@ -127,7 +128,7 @@ impl IndexedVal for Layout { } /// Describes how the fields of a type are shaped in memory. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum FieldsShape { /// Scalar primitives and `!`, which never have fields. Primitive, @@ -177,7 +178,7 @@ impl FieldsShape { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum VariantsShape { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { index: VariantIdx }, @@ -196,7 +197,7 @@ pub enum VariantsShape { }, } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum TagEncoding { /// The tag directly stores the discriminant, but possibly with a smaller layout /// (so converting the tag to the discriminant can require sign extension). @@ -221,7 +222,7 @@ pub enum TagEncoding { /// Describes how values of the type are passed by target ABIs, /// in terms of categories of C types there are ABI rules for. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum ValueAbi { Uninhabited, Scalar(Scalar), @@ -250,7 +251,7 @@ impl ValueAbi { } /// Information about one scalar component of a Rust type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize)] pub enum Scalar { Initialized { /// The primitive type used to represent this value. @@ -280,7 +281,7 @@ impl Scalar { } /// Fundamental unit of memory access and layout. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize)] pub enum Primitive { /// The `bool` is the signedness of the `Integer` type. /// @@ -310,7 +311,7 @@ impl Primitive { } /// Enum representing the existing integer lengths. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] pub enum IntegerLength { I8, I16, @@ -320,7 +321,7 @@ pub enum IntegerLength { } /// Enum representing the existing float lengths. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] pub enum FloatLength { F16, F32, @@ -354,7 +355,7 @@ impl FloatLength { /// An identifier that specifies the address space that some operation /// should operate on. Special address spaces have an effect on code generation, /// depending on the target and the address spaces it implements. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct AddressSpace(pub u32); impl AddressSpace { @@ -369,7 +370,7 @@ impl AddressSpace { /// sequence: /// /// 254 (-2), 255 (-1), 0, 1, 2 -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] pub struct WrappingRange { pub start: u128, pub end: u128, @@ -420,7 +421,7 @@ impl Debug for WrappingRange { } /// General language calling conventions. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum CallConvention { C, Rust, diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs index 67752a5e629f..a7cebc4c132b 100644 --- a/compiler/stable_mir/src/crate_def.rs +++ b/compiler/stable_mir/src/crate_def.rs @@ -3,9 +3,10 @@ use crate::ty::{GenericArgs, Span, Ty}; use crate::{with, Crate, Symbol}; +use serde::Serialize; /// A unique identification number for each item accessible for the current compilation unit. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] pub struct DefId(pub(crate) usize); /// A trait for retrieving information about a particular definition. diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 8385856ae532..fe745326d819 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -27,6 +27,7 @@ pub use crate::error::*; use crate::mir::Body; use crate::mir::Mutability; use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty}; +use serde::Serialize; pub mod abi; #[macro_use] @@ -74,7 +75,7 @@ pub type TraitDecls = Vec; pub type ImplTraitDecls = Vec; /// Holds information about a crate. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub struct Crate { pub id: CrateNum, pub name: Symbol, @@ -98,7 +99,7 @@ impl Crate { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] pub enum ItemKind { Fn, Static, @@ -106,7 +107,7 @@ pub enum ItemKind { Ctor(CtorKind), } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] pub enum CtorKind { Const, Fn, @@ -116,6 +117,7 @@ pub type Filename = String; crate_def_with_ty! { /// Holds information about an item in a crate. + #[derive(Serialize)] pub CrateItem; } @@ -188,7 +190,7 @@ pub fn all_trait_impls() -> ImplTraitDecls { } /// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] pub struct Opaque(String); impl std::fmt::Display for Opaque { diff --git a/compiler/stable_mir/src/mir/alloc.rs b/compiler/stable_mir/src/mir/alloc.rs index ef1568151f2e..9e0cac67f0aa 100644 --- a/compiler/stable_mir/src/mir/alloc.rs +++ b/compiler/stable_mir/src/mir/alloc.rs @@ -4,11 +4,12 @@ use crate::mir::mono::{Instance, StaticDef}; use crate::target::{Endian, MachineInfo}; use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty}; use crate::{with, Error}; +use serde::Serialize; use std::io::Read; /// An allocation in the SMIR global memory can be either a function pointer, /// a static, or a "real" allocation with some data in it. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub enum GlobalAlloc { /// The alloc ID is used as a function pointer. Function(Instance), @@ -41,7 +42,7 @@ impl GlobalAlloc { } /// A unique identification number for each provenance -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] pub struct AllocId(usize); impl IndexedVal for AllocId { diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index e0f9e7ae67a0..f7457ecd38f4 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -5,10 +5,11 @@ use crate::ty::{ TyConst, TyKind, VariantIdx, }; use crate::{Error, Opaque, Span, Symbol}; +use serde::Serialize; use std::io; /// The SMIR representation of a single function. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize)] pub struct Body { pub blocks: Vec, @@ -104,20 +105,20 @@ impl Body { type LocalDecls = Vec; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct LocalDecl { pub ty: Ty, pub span: Span, pub mutability: Mutability, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub struct BasicBlock { pub statements: Vec, pub terminator: Terminator, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Terminator { pub kind: TerminatorKind, pub span: Span, @@ -131,7 +132,7 @@ impl Terminator { pub type Successors = Vec; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum TerminatorKind { Goto { target: BasicBlockIdx, @@ -221,7 +222,7 @@ impl TerminatorKind { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct InlineAsmOperand { pub in_value: Option, pub out_place: Option, @@ -230,7 +231,7 @@ pub struct InlineAsmOperand { pub raw_rpr: String, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum UnwindAction { Continue, Unreachable, @@ -238,7 +239,7 @@ pub enum UnwindAction { Cleanup(BasicBlockIdx), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AssertMessage { BoundsCheck { len: Operand, index: Operand }, Overflow(BinOp, Operand, Operand), @@ -307,7 +308,7 @@ impl AssertMessage { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum BinOp { Add, AddUnchecked, @@ -342,7 +343,7 @@ impl BinOp { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum UnOp { Not, Neg, @@ -357,20 +358,20 @@ impl UnOp { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum CoroutineKind { Desugared(CoroutineDesugaring, CoroutineSource), Coroutine(Movability), } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum CoroutineSource { Block, Closure, Fn, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum CoroutineDesugaring { Async, @@ -386,7 +387,7 @@ pub(crate) type LocalDefId = Opaque; pub(crate) type Coverage = Opaque; /// The FakeReadCause describes the type of pattern why a FakeRead statement exists. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum FakeReadCause { ForMatchGuard, ForMatchedPlace(LocalDefId), @@ -396,7 +397,7 @@ pub enum FakeReadCause { } /// Describes what kind of retag is to be performed -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] pub enum RetagKind { FnEntry, TwoPhase, @@ -404,7 +405,7 @@ pub enum RetagKind { Default, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] pub enum Variance { Covariant, Invariant, @@ -412,26 +413,26 @@ pub enum Variance { Bivariant, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct CopyNonOverlapping { pub src: Operand, pub dst: Operand, pub count: Operand, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum NonDivergingIntrinsic { Assume(Operand), CopyNonOverlapping(CopyNonOverlapping), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Statement { pub kind: StatementKind, pub span: Span, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum StatementKind { Assign(Place, Rvalue), FakeRead(FakeReadCause, Place), @@ -448,7 +449,7 @@ pub enum StatementKind { Nop, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum Rvalue { /// Creates a pointer with the indicated mutability to the place. /// @@ -622,7 +623,7 @@ impl Rvalue { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AggregateKind { Array(Ty), Tuple, @@ -633,14 +634,14 @@ pub enum AggregateKind { RawPtr(Ty, Mutability), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum Operand { Copy(Place), Move(Place), Constant(ConstOperand), } -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Serialize)] pub struct Place { pub local: Local, /// projection out of a place (access a field, deref a pointer, etc) @@ -653,7 +654,7 @@ impl From for Place { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ConstOperand { pub span: Span, pub user_ty: Option, @@ -661,7 +662,7 @@ pub struct ConstOperand { } /// Debug information pertaining to a user variable. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct VarDebugInfo { /// The variable name. pub name: Symbol, @@ -703,19 +704,19 @@ impl VarDebugInfo { pub type SourceScope = u32; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct SourceInfo { pub span: Span, pub scope: SourceScope, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct VarDebugInfoFragment { pub ty: Ty, pub projection: Vec, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum VarDebugInfoContents { Place(Place), Const(ConstOperand), @@ -726,7 +727,7 @@ pub enum VarDebugInfoContents { // ProjectionElem) and user-provided type annotations (for which the projection elements // are of type ProjectionElem<(), ()>). In SMIR we don't need this generality, so we just use // ProjectionElem for Places. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ProjectionElem { /// Dereference projections (e.g. `*_1`) project to the address referenced by the base place. Deref, @@ -800,7 +801,7 @@ pub enum ProjectionElem { Subtype(Ty), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, @@ -830,7 +831,7 @@ pub type FieldIdx = usize; type UserTypeAnnotationIndex = usize; /// The possible branch sites of a [TerminatorKind::SwitchInt]. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct SwitchTargets { /// The conditional branches where the first element represents the value that guards this /// branch, and the second element is the branch target. @@ -867,7 +868,7 @@ impl SwitchTargets { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Shared, @@ -894,14 +895,14 @@ impl BorrowKind { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum MutBorrowKind { Default, TwoPhaseBorrow, ClosureCapture, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum FakeBorrowKind { /// A shared (deep) borrow. Data must be immutable and is aliasable. Deep, @@ -912,19 +913,19 @@ pub enum FakeBorrowKind { Shallow, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum Mutability { Not, Mut, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum Safety { Safe, Unsafe, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum PointerCoercion { /// Go from a fn-item type to a fn-pointer type. ReifyFnPointer, @@ -951,7 +952,7 @@ pub enum PointerCoercion { Unsize, } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub enum CastKind { // FIXME(smir-rename): rename this to PointerExposeProvenance PointerExposeAddress, @@ -967,7 +968,7 @@ pub enum CastKind { Transmute, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum NullOp { /// Returns the size of a value of that type. SizeOf, diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 572f1499c5a5..c23293388f93 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -3,17 +3,18 @@ use crate::crate_def::CrateDef; use crate::mir::Body; use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty}; use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol}; +use serde::Serialize; use std::fmt::{Debug, Formatter}; use std::io; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum MonoItem { Fn(Instance), Static(StaticDef), GlobalAsm(Opaque), } -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize)] pub struct Instance { /// The type of instance. pub kind: InstanceKind, @@ -22,7 +23,7 @@ pub struct Instance { pub def: InstanceDef, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum InstanceKind { /// A user defined item. Item, @@ -240,7 +241,7 @@ impl From for CrateItem { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] pub struct InstanceDef(usize); impl CrateDef for InstanceDef { @@ -251,6 +252,7 @@ impl CrateDef for InstanceDef { crate_def! { /// Holds information about a static variable definition. + #[derive(Serialize)] pub StaticDef; } diff --git a/compiler/stable_mir/src/target.rs b/compiler/stable_mir/src/target.rs index e00a418c5403..9fb5e046abc3 100644 --- a/compiler/stable_mir/src/target.rs +++ b/compiler/stable_mir/src/target.rs @@ -1,9 +1,10 @@ //! Provide information about the machine that this is being compiled into. use crate::compiler_interface::with; +use serde::Serialize; /// The properties of the target machine being compiled into. -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Serialize)] pub struct MachineInfo { pub endian: Endian, pub pointer_width: MachineSize, @@ -23,14 +24,14 @@ impl MachineInfo { } } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Serialize)] pub enum Endian { Little, Big, } /// Represent the size of a component. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] pub struct MachineSize { num_bits: usize, } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 8c120a96e75b..9c8921da52ff 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -8,10 +8,11 @@ use crate::mir::alloc::{read_target_int, read_target_uint, AllocId}; use crate::mir::mono::StaticDef; use crate::target::MachineInfo; use crate::{Filename, Opaque}; +use serde::Serialize; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; -#[derive(Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] pub struct Ty(usize); impl Debug for Ty { @@ -100,13 +101,13 @@ impl Ty { } /// Represents a pattern in the type system -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum Pattern { Range { start: Option, end: Option, include_end: bool }, } /// Represents a constant in the type system -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct TyConst { pub(crate) kind: TyConstKind, pub id: TyConstId, @@ -133,7 +134,7 @@ impl TyConst { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum TyConstKind { Param(ParamConst), Bound(DebruijnIndex, BoundVar), @@ -144,11 +145,11 @@ pub enum TyConstKind { ZSTValue(Ty), } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)] pub struct TyConstId(usize); /// Represents a constant in MIR -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct MirConst { /// The constant kind. pub(crate) kind: ConstantKind, @@ -205,17 +206,17 @@ impl MirConst { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub struct MirConstId(usize); type Ident = Opaque; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Region { pub kind: RegionKind, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum RegionKind { ReEarlyParam(EarlyParamRegion), ReBound(DebruijnIndex, BoundRegion), @@ -226,7 +227,7 @@ pub enum RegionKind { pub(crate) type DebruijnIndex = u32; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct EarlyParamRegion { pub index: u32, pub name: Symbol, @@ -234,7 +235,7 @@ pub struct EarlyParamRegion { pub(crate) type BoundVar = u32; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct BoundRegion { pub var: BoundVar, pub kind: BoundRegionKind, @@ -242,13 +243,13 @@ pub struct BoundRegion { pub(crate) type UniverseIndex = u32; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, } -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Serialize)] pub struct Span(usize); impl Debug for Span { @@ -272,7 +273,7 @@ impl Span { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Serialize)] /// Information you get from `Span` in a struct form. /// Line and col start from 1. pub struct LineInfo { @@ -282,7 +283,7 @@ pub struct LineInfo { pub end_col: usize, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum TyKind { RigidTy(RigidTy), Alias(AliasKind, AliasTy), @@ -521,7 +522,7 @@ pub struct TypeAndMut { pub mutability: Mutability, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum RigidTy { Bool, Char, @@ -560,7 +561,7 @@ impl From for TyKind { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub enum IntTy { Isize, I8, @@ -583,7 +584,7 @@ impl IntTy { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub enum UintTy { Usize, U8, @@ -606,19 +607,20 @@ impl UintTy { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub enum FloatTy { F32, F64, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub enum Movability { Static, Movable, } crate_def! { + #[derive(Serialize)] pub ForeignModuleDef; } @@ -641,6 +643,7 @@ impl ForeignModule { crate_def_with_ty! { /// Hold information about a ForeignItem in a crate. + #[derive(Serialize)] pub ForeignDef; } @@ -650,7 +653,7 @@ impl ForeignDef { } } -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] pub enum ForeignItemKind { Fn(FnDef), Static(StaticDef), @@ -659,6 +662,7 @@ pub enum ForeignItemKind { crate_def_with_ty! { /// Hold information about a function definition in a crate. + #[derive(Serialize)] pub FnDef; } @@ -692,6 +696,7 @@ impl FnDef { } crate_def_with_ty! { + #[derive(Serialize)] pub IntrinsicDef; } @@ -716,26 +721,31 @@ impl From for FnDef { } crate_def! { + #[derive(Serialize)] pub ClosureDef; } crate_def! { + #[derive(Serialize)] pub CoroutineDef; } crate_def! { + #[derive(Serialize)] pub ParamDef; } crate_def! { + #[derive(Serialize)] pub BrNamedDef; } -crate_def_with_ty! { +crate_def! { + #[derive(Serialize)] pub AdtDef; } -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] pub enum AdtKind { Enum, Union, @@ -789,7 +799,7 @@ impl AdtDef { } /// Definition of a variant, which can be either a struct / union field or an enum variant. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] pub struct VariantDef { /// The variant index. /// @@ -818,7 +828,7 @@ impl VariantDef { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct FieldDef { /// The field definition. /// @@ -869,11 +879,13 @@ impl AdtKind { } crate_def! { + #[derive(Serialize)] pub AliasDef; } crate_def! { /// A trait's definition. + #[derive(Serialize)] pub TraitDef; } @@ -884,15 +896,18 @@ impl TraitDef { } crate_def! { + #[derive(Serialize)] pub GenericDef; } crate_def_with_ty! { + #[derive(Serialize)] pub ConstDef; } crate_def! { /// A trait impl definition. + #[derive(Serialize)] pub ImplDef; } @@ -904,15 +919,17 @@ impl ImplDef { } crate_def! { + #[derive(Serialize)] pub RegionDef; } crate_def! { + #[derive(Serialize)] pub CoroutineWitnessDef; } /// A list of generic arguments. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct GenericArgs(pub Vec); impl std::ops::Index for GenericArgs { @@ -931,7 +948,7 @@ impl std::ops::Index for GenericArgs { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum GenericArgKind { Lifetime(Region), Type(Ty), @@ -968,13 +985,13 @@ impl GenericArgKind { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum TermKind { Type(Ty), Const(TyConst), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AliasKind { Projection, Inherent, @@ -982,13 +999,13 @@ pub enum AliasKind { Weak, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct AliasTy { pub def_id: AliasDef, pub args: GenericArgs, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct AliasTerm { pub def_id: AliasDef, pub args: GenericArgs, @@ -1006,7 +1023,7 @@ impl PolyFnSig { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct FnSig { pub inputs_and_output: Vec, pub c_variadic: bool, @@ -1024,7 +1041,7 @@ impl FnSig { } } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub enum Abi { Rust, C { unwind: bool }, @@ -1054,7 +1071,7 @@ pub enum Abi { } /// A binder represents a possibly generic type and its bound vars. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Binder { pub value: T, pub bound_vars: Vec, @@ -1094,38 +1111,38 @@ impl Binder { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct EarlyBinder { pub value: T, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum BoundVariableKind { Ty(BoundTyKind), Region(BoundRegionKind), Const, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] pub enum BoundTyKind { Anon, Param(ParamDef, String), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum BoundRegionKind { BrAnon, BrNamed(BrNamedDef, String), BrEnv, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum DynKind { Dyn, DynStar, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ExistentialPredicate { Trait(ExistentialTraitRef), Projection(ExistentialProjection), @@ -1135,7 +1152,7 @@ pub enum ExistentialPredicate { /// An existential reference to a trait where `Self` is not included. /// /// The `generic_args` will include any other known argument. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ExistentialTraitRef { pub def_id: TraitDef, pub generic_args: GenericArgs, @@ -1153,20 +1170,20 @@ impl ExistentialTraitRef { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ExistentialProjection { pub def_id: TraitDef, pub generic_args: GenericArgs, pub term: TermKind, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ParamTy { pub index: u32, pub name: String, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct BoundTy { pub var: usize, pub kind: BoundTyKind, @@ -1177,7 +1194,7 @@ pub type Bytes = Vec>; /// Size in bytes. pub type Size = usize; -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)] pub struct Prov(pub AllocId); pub type Align = u64; @@ -1185,14 +1202,14 @@ pub type Promoted = u32; pub type InitMaskMaterialized = Vec; /// Stores the provenance information of pointers stored in memory. -#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] pub struct ProvenanceMap { /// Provenance in this map applies from the given offset for an entire pointer-size worth of /// bytes. Two entries in this map are always at least a pointer size apart. pub ptrs: Vec<(Size, Prov)>, } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)] pub struct Allocation { pub bytes: Bytes, pub provenance: ProvenanceMap, @@ -1268,7 +1285,7 @@ impl Allocation { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ConstantKind { Ty(TyConst), Allocated(Allocation), @@ -1279,27 +1296,27 @@ pub enum ConstantKind { ZeroSized, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ParamConst { pub index: u32, pub name: String, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct UnevaluatedConst { pub def: ConstDef, pub args: GenericArgs, pub promoted: Option, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub enum TraitSpecializationKind { None, Marker, AlwaysApplicable, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct TraitDecl { pub def_id: TraitDef, pub safety: Safety, @@ -1332,7 +1349,7 @@ impl TraitDecl { pub type ImplTrait = EarlyBinder; /// A complete reference to a trait, i.e., one where `Self` is known. -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct TraitRef { pub def_id: TraitDef, /// The generic arguments for this definition. @@ -1366,7 +1383,7 @@ impl TraitRef { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct Generics { pub parent: Option, pub parent_count: usize, @@ -1377,14 +1394,14 @@ pub struct Generics { pub host_effect_index: Option, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, Const { has_default: bool }, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct GenericParamDef { pub name: super::Symbol, pub def_id: GenericDef, @@ -1398,7 +1415,7 @@ pub struct GenericPredicates { pub predicates: Vec<(PredicateKind, Span)>, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum PredicateKind { Clause(ClauseKind), ObjectSafe(TraitDef), @@ -1409,7 +1426,7 @@ pub enum PredicateKind { AliasRelate(TermKind, TermKind, AliasRelationDirection), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ClauseKind { Trait(TraitPredicate), RegionOutlives(RegionOutlivesPredicate), @@ -1420,57 +1437,57 @@ pub enum ClauseKind { ConstEvaluatable(TyConst), } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ClosureKind { Fn, FnMut, FnOnce, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct SubtypePredicate { pub a: Ty, pub b: Ty, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct CoercePredicate { pub a: Ty, pub b: Ty, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AliasRelationDirection { Equate, Subtype, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct TraitPredicate { pub trait_ref: TraitRef, pub polarity: PredicatePolarity, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct OutlivesPredicate(pub A, pub B); pub type RegionOutlivesPredicate = OutlivesPredicate; pub type TypeOutlivesPredicate = OutlivesPredicate; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct ProjectionPredicate { pub projection_term: AliasTerm, pub term: TermKind, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ImplPolarity { Positive, Negative, Reservation, } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum PredicatePolarity { Positive, Negative, @@ -1513,7 +1530,7 @@ index_impl!(Span); /// `a` is in the variant with the `VariantIdx` of `0`, /// `c` is in the variant with the `VariantIdx` of `1`, and /// `g` is in the variant with the `VariantIdx` of `0`. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] pub struct VariantIdx(usize); index_impl!(VariantIdx); diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs new file mode 100644 index 000000000000..957d840f7a24 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -0,0 +1,75 @@ +//@ run-pass +//! Test that users are able to use serialize stable MIR constructs. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +//@ edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate stable_mir; +extern crate serde; +extern crate serde_json; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use stable_mir::mir::Body; +use std::io::{Write, BufWriter}; +use std::ops::ControlFlow; +use serde_json::to_string; + + +const CRATE_NAME: &str = "input"; + +fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let path = "output.json"; + let mut writer = BufWriter::new(std::fs::File::create(path) + .expect("Failed to create path")); + let local_crate = stable_mir::local_crate(); + let items: Vec = stable_mir::all_local_items() + .iter() + .map(|item| { item.body() }) + .collect(); + let crate_data = ( local_crate.name, items ); + writer.write_all(to_string(&crate_data) + .expect("serde_json failed") + .as_bytes()).expect("JSON serialization failed"); + ControlFlow::Continue(()) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "internal_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run_with_tcx!(args, serialize_to_json).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn main() {{ + }} + "# + )?; + Ok(()) +} From 1f41fbe0ef6685a97d9d04056c2de3020aa81775 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 1 Jul 2024 20:39:48 +0100 Subject: [PATCH 02/49] introduce tests --- tests/ui/dropck/const_drop_is_valid.rs | 11 + tests/ui/dropck/const_drop_is_valid.stderr | 45 ++++ .../constrained_by_assoc_type_equality.rs | 12 + .../constrained_by_assoc_type_equality.stderr | 15 ++ .../unconstrained_const_param_on_drop.rs | 8 + .../unconstrained_const_param_on_drop.stderr | 219 ++++++++++++++++++ 6 files changed, 310 insertions(+) create mode 100644 tests/ui/dropck/const_drop_is_valid.rs create mode 100644 tests/ui/dropck/const_drop_is_valid.stderr create mode 100644 tests/ui/dropck/constrained_by_assoc_type_equality.rs create mode 100644 tests/ui/dropck/constrained_by_assoc_type_equality.stderr create mode 100644 tests/ui/dropck/unconstrained_const_param_on_drop.rs create mode 100644 tests/ui/dropck/unconstrained_const_param_on_drop.stderr diff --git a/tests/ui/dropck/const_drop_is_valid.rs b/tests/ui/dropck/const_drop_is_valid.rs new file mode 100644 index 000000000000..0441b6ed067a --- /dev/null +++ b/tests/ui/dropck/const_drop_is_valid.rs @@ -0,0 +1,11 @@ +#![feature(effects)] +//~^ WARN: the feature `effects` is incomplete + +struct A(); + +impl const Drop for A {} +//~^ ERROR: const trait impls are experimental +//~| const `impl` for trait `Drop` which is not marked with `#[const_trait]` +//~| not all trait items implemented, missing: `drop` + +fn main() {} diff --git a/tests/ui/dropck/const_drop_is_valid.stderr b/tests/ui/dropck/const_drop_is_valid.stderr new file mode 100644 index 000000000000..f15b7ba946db --- /dev/null +++ b/tests/ui/dropck/const_drop_is_valid.stderr @@ -0,0 +1,45 @@ +error[E0658]: const trait impls are experimental + --> $DIR/const_drop_is_valid.rs:6:6 + | +LL | impl const Drop for A {} + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const_drop_is_valid.rs:1:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const_drop_is_valid.rs:6:12 + | +LL | impl const Drop for A {} + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/const_drop_is_valid.rs:6:1 + | +LL | impl const Drop for A {} + | ^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0046, E0658. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality.rs b/tests/ui/dropck/constrained_by_assoc_type_equality.rs new file mode 100644 index 000000000000..521806cc1d7a --- /dev/null +++ b/tests/ui/dropck/constrained_by_assoc_type_equality.rs @@ -0,0 +1,12 @@ +struct Foo(T); + +trait Trait { + type Assoc; +} + +impl, U: ?Sized> Drop for Foo { + //~^ ERROR: `Drop` impl requires `::Assoc == U` + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality.stderr b/tests/ui/dropck/constrained_by_assoc_type_equality.stderr new file mode 100644 index 000000000000..29f4881c3fbe --- /dev/null +++ b/tests/ui/dropck/constrained_by_assoc_type_equality.stderr @@ -0,0 +1,15 @@ +error[E0367]: `Drop` impl requires `::Assoc == U` but the struct it is implemented for does not + --> $DIR/constrained_by_assoc_type_equality.rs:7:15 + | +LL | impl, U: ?Sized> Drop for Foo { + | ^^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/constrained_by_assoc_type_equality.rs:1:1 + | +LL | struct Foo(T); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.rs b/tests/ui/dropck/unconstrained_const_param_on_drop.rs new file mode 100644 index 000000000000..369ec7280bd3 --- /dev/null +++ b/tests/ui/dropck/unconstrained_const_param_on_drop.rs @@ -0,0 +1,8 @@ +//@ known-bug: unknown +//@ failure-status: 101 + +struct Foo {} + +impl Drop for Foo {} + +fn main() {} diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr new file mode 100644 index 000000000000..b48ae8cc8af2 --- /dev/null +++ b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr @@ -0,0 +1,219 @@ +thread 'rustc' panicked at compiler/rustc_middle/src/ty/sty.rs:360:36: +called `Option::unwrap()` on a `None` value +stack backtrace: + 0: begin_panic_handler + at ./library/std/src/panicking.rs:661:5 + 1: panic_fmt + at ./library/core/src/panicking.rs:74:14 + 2: panic + at ./library/core/src/panicking.rs:148:5 + 3: core::option::unwrap_failed + at ./library/core/src/option.rs:2013:5 + 4: unwrap + at ./library/core/src/option.rs:963:21 + 5: find_ty_from_env + at ./compiler/rustc_middle/src/ty/sty.rs:360:36 + 6: process_obligation + at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:472:29 + 7: process_obligations + at ./compiler/rustc_data_structures/src/obligation_forest/mod.rs:462:23 + 8: select + at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:107:13 + 9: select_where_possible + at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:160:9 + 10: select_all_or_error, rustc_trait_selection::traits::FulfillmentError> + at ./compiler/rustc_infer/src/traits/engine.rs:82:22 + 11: select_all_or_error + at ./compiler/rustc_trait_selection/src/traits/engine.rs:189:9 + 12: ensure_drop_predicates_are_implied_by_item_defn + at ./compiler/rustc_hir_analysis/src/check/dropck.rs:154:18 + 13: check_drop_impl + at ./compiler/rustc_hir_analysis/src/check/dropck.rs:60:13 + 14: call core::result::Result<(), rustc_span::ErrorGuaranteed>, (rustc_middle::ty::context::TyCtxt, rustc_span::def_id::DefId)> + at ./library/core/src/ops/function.rs:79:5 + 15: {closure#0} core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/util.rs:360:16 + 16: for_each_relevant_impl core::result::Result<(), rustc_span::ErrorGuaranteed>>> + at ./compiler/rustc_middle/src/ty/trait_def.rs:166:21 + 17: calculate_dtor core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/util.rs:359:9 + 18: rustc_hir_analysis::check::adt_destructor + at ./compiler/rustc_hir_analysis/src/check/mod.rs:125:5 + 19: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:285:13 + [... omitted 22 frames ...] + 20: query_get_at>> + at ./compiler/rustc_middle/src/query/plumbing.rs:145:17 + 21: adt_destructor + at ./compiler/rustc_middle/src/query/plumbing.rs:423:31 + 22: adt_destructor + at ./compiler/rustc_middle/src/query/plumbing.rs:414:35 + 23: destructor + at ./compiler/rustc_middle/src/ty/adt.rs:610:13 + 24: check_struct + at ./compiler/rustc_hir_analysis/src/check/check.rs:71:5 + 25: check_item_type + at ./compiler/rustc_hir_analysis/src/check/check.rs:730:13 + 26: check_item + at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:335:5 + 27: check_well_formed + at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:192:39 + 28: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 + [... omitted 22 frames ...] + 29: query_ensure_error_guaranteed>, ()> + at ./compiler/rustc_middle/src/query/plumbing.rs:181:9 + 30: check_well_formed + at ./compiler/rustc_middle/src/query/plumbing.rs:199:9 + 31: {closure#1} + at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:1995:47 + 32: {closure#0} + at ./compiler/rustc_middle/src/hir/mod.rs:89:57 + 33: {closure#0}<&[rustc_hir::hir::ImplItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_impl_items::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:203:50 + 34: call_once, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure#0}::{closure_env#0}<&[rustc_hir::hir::ImplItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_impl_items::{closure_env#0}>> + at ./library/core/src/panic/unwind_safe.rs:272:9 + 35: do_call>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/panicking.rs:553:40 + 36: try, core::panic::unwind_safe::AssertUnwindSafe>>> + at ./library/std/src/panicking.rs:517:19 + 37: catch_unwind>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/panic.rs:350:14 + 38: run, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure#2}::{closure_env#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:28:9 + 39: {closure#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:206:46 + 40: {closure#0}<&rustc_hir::hir::ItemId, core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/core/src/iter/adapters/filter_map.rs:39:28 + 41: fold, core::iter::adapters::filter_map::filter_map_fold::{closure_env#0}<&rustc_hir::hir::ItemId, core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>>> + at ./library/core/src/slice/iter/macros.rs:232:27 + 42: fold, core::slice::iter::Iter, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/core/src/iter/adapters/filter_map.rs:148:9 + 43: {closure#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:206:73 + 44: parallel_guard, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure_env#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:44:15 + 45: try_par_for_each_in<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:199:9 + 46: par_items + at ./compiler/rustc_middle/src/hir/mod.rs:75:9 + 47: check_mod_type_wf + at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:1994:19 + 48: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 + [... omitted 22 frames ...] + 49: query_ensure_error_guaranteed>, ()> + at ./compiler/rustc_middle/src/query/plumbing.rs:181:9 + 50: check_mod_type_wf + at ./compiler/rustc_middle/src/query/plumbing.rs:199:9 + 51: {closure#0} + at ./compiler/rustc_hir_analysis/src/lib.rs:162:21 + 52: {closure#0} + at ./compiler/rustc_middle/src/hir/map/mod.rs:463:13 + 53: {closure#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:34 + 54: call_once<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#0}::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> + at ./library/core/src/panic/unwind_safe.rs:272:9 + 55: do_call>>, ()> + at ./library/std/src/panicking.rs:553:40 + 56: try<(), core::panic::unwind_safe::AssertUnwindSafe>>> + at ./library/std/src/panicking.rs:517:19 + 57: catch_unwind>>, ()> + at ./library/std/src/panic.rs:350:14 + 58: run<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:28:9 + 59: {closure#1}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:186:21 + 60: for_each>> + at ./library/core/src/slice/iter/macros.rs:254:21 + 61: {closure#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:185:17 + 62: parallel_guard<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:44:15 + 63: par_for_each_in<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:178:9 + 64: par_for_each_module + at ./compiler/rustc_middle/src/hir/map/mod.rs:462:9 + 65: {closure#0} + at ./compiler/rustc_hir_analysis/src/lib.rs:161:9 + 66: run<(), rustc_hir_analysis::check_crate::{closure_env#0}> + at ./compiler/rustc_data_structures/src/profiling.rs:754:9 + 67: time<(), rustc_hir_analysis::check_crate::{closure_env#0}> + at ./compiler/rustc_session/src/utils.rs:16:9 + 68: check_crate + at ./compiler/rustc_hir_analysis/src/lib.rs:160:5 + 69: run_required_analyses + at ./compiler/rustc_interface/src/passes.rs:784:5 + 70: analysis + at ./compiler/rustc_interface/src/passes.rs:823:5 + 71: {closure#0} + at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 + [... omitted 22 frames ...] + 72: query_get_at>> + at ./compiler/rustc_middle/src/query/plumbing.rs:145:17 + 73: analysis + at ./compiler/rustc_middle/src/query/plumbing.rs:423:31 + 74: analysis + at ./compiler/rustc_middle/src/query/plumbing.rs:414:35 + 75: {closure#5} + at ./compiler/rustc_driver_impl/src/lib.rs:445:52 + 76: {closure#1}> + at ./compiler/rustc_middle/src/ty/context.rs:1296:37 + 77: {closure#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/context/tls.rs:82:9 + 78: try_with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/thread/local.rs:283:12 + 79: with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./library/std/src/thread/local.rs:260:9 + 80: enter_context>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_middle/src/ty/context/tls.rs:79:9 + 81: enter> + at ./compiler/rustc_middle/src/ty/context.rs:1296:9 + 82: {closure#1} + at ./compiler/rustc_driver_impl/src/lib.rs:445:13 + 83: enter, rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/queries.rs:202:19 + 84: {closure#0} + at ./compiler/rustc_driver_impl/src/lib.rs:389:22 + 85: {closure#1}, rustc_driver_impl::run_compiler::{closure_env#0}> + at ./compiler/rustc_interface/src/interface.rs:502:27 + 86: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:154:13 + 87: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:106:21 + 88: set, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at /home/boxy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-1.0.1/src/lib.rs:137:9 + 89: create_session_globals_then, rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>> + at ./compiler/rustc_span/src/lib.rs:134:5 + 90: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> + at ./compiler/rustc_interface/src/util.rs:105:17 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + +error: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md + +note: please make sure that you have updated to the latest nightly + +note: rustc 1.81.0-dev running on x86_64-unknown-linux-gnu + +note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/home/boxy/.cargo -Z ignore-directory-in-diagnostics-source-blocks=/media/Nyoomies/Repos/rust/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 + +query stack during panic: +#0 [adt_destructor] computing `Drop` impl for `Foo` +#1 [check_well_formed] checking that `Foo` is well-formed +#2 [check_mod_type_wf] checking that types are well-formed in top-level module +#3 [analysis] running analysis passes on this crate +end of query stack +error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates + --> $DIR/unconstrained_const_param_on_drop.rs:6:6 + | +LL | impl Drop for Foo {} + | ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`. From 6a0000827671ab12837a5a3a692d5dd9c31def69 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 1 Jul 2024 21:43:00 +0100 Subject: [PATCH 03/49] Rewrite dropck --- .../rustc_hir_analysis/src/check/dropck.rs | 34 ++- .../constrained_by_assoc_type_equality.rs | 3 +- ...ined_by_assoc_type_equality_and_self_ty.rs | 12 + ...by_assoc_type_equality_and_self_ty.stderr} | 10 +- .../dropck/reject-specialized-drops-8142.rs | 166 +++++++++---- .../reject-specialized-drops-8142.stderr | 167 ++++++------- .../ui/dropck/transitive-outlives.bad.stderr | 9 +- tests/ui/dropck/transitive-outlives.rs | 2 +- .../unconstrained_const_param_on_drop.rs | 5 +- .../unconstrained_const_param_on_drop.stderr | 224 ++---------------- 10 files changed, 265 insertions(+), 367 deletions(-) create mode 100644 tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs rename tests/ui/dropck/{constrained_by_assoc_type_equality.stderr => constrained_by_assoc_type_equality_and_self_ty.stderr} (53%) diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 193714480255..06ec01484a41 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; -use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{GenericArgsRef, Ty}; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -115,8 +115,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( Err(err.emit()) } -/// Confirms that every predicate imposed by dtor_predicates is -/// implied by assuming the predicates attached to self_type_did. +/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be +/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are +/// implied by the ADT being well formed. fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, drop_impl_def_id: LocalDefId, @@ -126,6 +127,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let infcx = tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let impl_span = tcx.def_span(drop_impl_def_id.to_def_id()); + // Take the param-env of the adt and instantiate the args that show up in // the implementation's self type. This gives us the assumptions that the // self ty of the implementation is allowed to know just from it being a @@ -135,14 +138,27 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // We don't need to normalize this param-env or anything, since we're only // instantiating it with free params, so no additional param-env normalization // can occur on top of what has been done in the param_env query itself. - let param_env = + // + // Note: Ideally instead of instantiating the `ParamEnv` with the arguments from the impl ty we + // could instead use identity args for the adt. Unfortunately this would cause any errors to + // reference the params from the ADT instead of from the impl which is bad UX. To resolve + // this we "rename" the ADT's params to be the impl's params which should not affect behaviour. + let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args); + let adt_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); - for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) { + let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id()); + let fresh_adt_ty = + tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty(); + + ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty) + .unwrap(); + + for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) { let normalize_cause = traits::ObligationCause::misc(span, adt_def_id); - let pred = ocx.normalize(&normalize_cause, param_env, pred); + let pred = ocx.normalize(&normalize_cause, adt_env, clause); let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl); - ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred)); + ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred)); } // All of the custom error reporting logic is to preserve parity with the old @@ -176,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( return Err(guar.unwrap()); } - let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env)); + let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(adt_env)); if !errors.is_empty() { let mut guar = None; for error in errors { diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality.rs b/tests/ui/dropck/constrained_by_assoc_type_equality.rs index 521806cc1d7a..4101fe83c3be 100644 --- a/tests/ui/dropck/constrained_by_assoc_type_equality.rs +++ b/tests/ui/dropck/constrained_by_assoc_type_equality.rs @@ -1,3 +1,5 @@ +//@ check-pass + struct Foo(T); trait Trait { @@ -5,7 +7,6 @@ trait Trait { } impl, U: ?Sized> Drop for Foo { - //~^ ERROR: `Drop` impl requires `::Assoc == U` fn drop(&mut self) {} } diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs new file mode 100644 index 000000000000..3a85b86cb1fd --- /dev/null +++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs @@ -0,0 +1,12 @@ +trait Trait { + type Assoc; +} + +struct Foo(T, U); + +impl, U: ?Sized> Drop for Foo { + //~^ ERROR: `Drop` impl requires `::Assoc == U` + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality.stderr b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr similarity index 53% rename from tests/ui/dropck/constrained_by_assoc_type_equality.stderr rename to tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr index 29f4881c3fbe..dab8c55d0e7f 100644 --- a/tests/ui/dropck/constrained_by_assoc_type_equality.stderr +++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr @@ -1,14 +1,14 @@ error[E0367]: `Drop` impl requires `::Assoc == U` but the struct it is implemented for does not - --> $DIR/constrained_by_assoc_type_equality.rs:7:15 + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:7:15 | -LL | impl, U: ?Sized> Drop for Foo { +LL | impl, U: ?Sized> Drop for Foo { | ^^^^^^^^^ | note: the implementor must specify the same requirement - --> $DIR/constrained_by_assoc_type_equality.rs:1:1 + --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:5:1 | -LL | struct Foo(T); - | ^^^^^^^^^^^^^^^^^^^^ +LL | struct Foo(T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/dropck/reject-specialized-drops-8142.rs b/tests/ui/dropck/reject-specialized-drops-8142.rs index 7a3bbe7cb093..1b73fe9a0655 100644 --- a/tests/ui/dropck/reject-specialized-drops-8142.rs +++ b/tests/ui/dropck/reject-specialized-drops-8142.rs @@ -1,75 +1,145 @@ // Issue 8142: Test that Drop impls cannot be specialized beyond the // predicates attached to the type definition itself. -trait Bound { fn foo(&self) { } } -struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } -struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } -struct M<'m> { x: &'m i8 } -struct N<'n> { x: &'n i8 } -struct O { x: *const To } -struct P { x: *const Tp } -struct Q { x: *const Tq } -struct R { x: *const Tr } -struct S { x: *const Ts } -struct T<'t,Ts:'t> { x: &'t Ts } +trait Bound { + fn foo(&self) {} +} +struct K<'l1, 'l2> { + x: &'l1 i8, + y: &'l2 u8, +} +struct L<'l1, 'l2> { + x: &'l1 i8, + y: &'l2 u8, +} +struct M<'m> { + x: &'m i8, +} +struct N<'n> { + x: &'n i8, +} +struct O { + x: *const To, +} +struct P { + x: *const Tp, +} +struct Q { + x: *const Tq, +} +struct R { + x: *const Tr, +} +struct S { + x: *const Ts, +} +struct T<'t, Ts: 't> { + x: &'t Ts, +} struct U; -struct V { x: *const Tva, y: *const Tvb } -struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } +struct V { + x: *const Tva, + y: *const Tvb, +} +struct W<'l1, 'l2> { + x: &'l1 i8, + y: &'l2 u8, +} struct X; struct Y; -enum Enum { Variant(T) } +enum Enum { + Variant(T), +} struct TupleStruct(T); -union Union { f: T } +union Union { + f: T, +} -impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT +impl<'al, 'adds_bnd: 'al> Drop for K<'al, 'adds_bnd> { //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` - fn drop(&mut self) { } } + fn drop(&mut self) {} +} -impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT - //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` - fn drop(&mut self) { } } +impl<'al, 'adds_bnd> Drop for L<'al, 'adds_bnd> +//~^ ERROR `Drop` impl requires `'adds_bnd: 'al` +where + 'adds_bnd: 'al, +{ + fn drop(&mut self) {} +} -impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT +impl<'ml> Drop for M<'ml> { + fn drop(&mut self) {} +} -impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl Drop for N<'static> { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl Drop for O { fn drop(&mut self) { } } // ACCEPT +impl Drop for O { + fn drop(&mut self) {} +} -impl Drop for P { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl Drop for P { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl Drop for Q { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +impl Drop for Q { + //~^ ERROR `Drop` impl requires `AddsBnd: Bound` + fn drop(&mut self) {} +} -impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd` +impl<'rbnd, AddsRBnd: 'rbnd> Drop for R { + fn drop(&mut self) {} +} -impl Drop for S { fn drop(&mut self) { } } // ACCEPT +impl Drop for S { + fn drop(&mut self) {} +} -impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT +impl<'t, Bt: 't> Drop for T<'t, Bt> { + fn drop(&mut self) {} +} -impl Drop for U { fn drop(&mut self) { } } // ACCEPT +impl Drop for U { + fn drop(&mut self) {} +} -impl Drop for V { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl Drop for V { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl<'lw> Drop for W<'lw, 'lw> { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl Drop for X<3> { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl Drop for X<3> { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl Drop for Y { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impls cannot be specialized +impl Drop for Y { + //~^ ERROR `Drop` impls cannot be specialized + fn drop(&mut self) {} +} -impl Drop for Enum { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +impl Drop for Enum { + //~^ ERROR `Drop` impl requires `AddsBnd: Bound` + fn drop(&mut self) {} +} -impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +impl Drop for TupleStruct { + //~^ ERROR `Drop` impl requires `AddsBnd: Bound` + fn drop(&mut self) {} +} -impl Drop for Union { fn drop(&mut self) { } } // REJECT -//~^ ERROR `Drop` impl requires `AddsBnd: Bound` +impl Drop for Union { + //~^ ERROR `Drop` impl requires `AddsBnd: Bound` + fn drop(&mut self) {} +} -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/dropck/reject-specialized-drops-8142.stderr b/tests/ui/dropck/reject-specialized-drops-8142.stderr index cb48221c67a8..9c8b6d544639 100644 --- a/tests/ui/dropck/reject-specialized-drops-8142.stderr +++ b/tests/ui/dropck/reject-specialized-drops-8142.stderr @@ -1,166 +1,157 @@ error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:24:20 + --> $DIR/reject-specialized-drops-8142.rs:58:1 | -LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT - | ^^^ +LL | impl<'al, 'adds_bnd: 'al> Drop for K<'al, 'adds_bnd> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:4:1 + --> $DIR/reject-specialized-drops-8142.rs:6:1 | -LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^^^^^^^^^^^^^^^ +LL | struct K<'l1, 'l2> { + | ^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:28:67 + --> $DIR/reject-specialized-drops-8142.rs:63:1 | -LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT - | ^^^ - | -note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:5:1 - | -LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^^^^^^^^^^^^^^^ - -error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:34:1 - | -LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `'static` is not a generic parameter -note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:7:1 - | -LL | struct N<'n> { x: &'n i8 } - | ^^^^^^^^^^^^ - -error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:39:1 - | -LL | impl Drop for P { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `i8` is not a generic parameter -note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:9:1 - | -LL | struct P { x: *const Tp } - | ^^^^^^^^^^^^ - -error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:42:14 - | -LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT - | ^^^^^ +LL | / impl<'al, 'adds_bnd> Drop for L<'al, 'adds_bnd> +LL | | +LL | | where +LL | | 'adds_bnd: 'al, + | |___________________^ | note: the implementor must specify the same requirement --> $DIR/reject-specialized-drops-8142.rs:10:1 | -LL | struct Q { x: *const Tq } - | ^^^^^^^^^^^^ +LL | struct L<'l1, 'l2> { + | ^^^^^^^^^^^^^^^^^^ -error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:45:21 +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:75:1 | -LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT - | ^^^^^ +LL | impl Drop for N<'static> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:11:1 + = note: `'static` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:17:1 | -LL | struct R { x: *const Tr } +LL | struct N<'n> { | ^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:54:1 + --> $DIR/reject-specialized-drops-8142.rs:84:1 | -LL | impl Drop for V { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Drop for P { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `i8` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:23:1 + | +LL | struct P { + | ^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:89:15 + | +LL | impl Drop for Q { + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:26:1 + | +LL | struct Q { + | ^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:110:1 + | +LL | impl Drop for V { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `One` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:15:1 + --> $DIR/reject-specialized-drops-8142.rs:39:1 | -LL | struct V { x: *const Tva, y: *const Tvb } +LL | struct V { | ^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:57:1 + --> $DIR/reject-specialized-drops-8142.rs:115:1 | -LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'lw> Drop for W<'lw, 'lw> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `'lw` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:16:1 + --> $DIR/reject-specialized-drops-8142.rs:43:1 | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } +LL | struct W<'l1, 'l2> { | ^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:60:1 + --> $DIR/reject-specialized-drops-8142.rs:120:1 | -LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Drop for X<3> { + | ^^^^^^^^^^^^^^^^^^ | = note: `3` is not a generic parameter note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:17:1 + --> $DIR/reject-specialized-drops-8142.rs:47:1 | LL | struct X; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0366]: `Drop` impls cannot be specialized - --> $DIR/reject-specialized-drops-8142.rs:63:1 + --> $DIR/reject-specialized-drops-8142.rs:125:1 | -LL | impl Drop for Y { fn drop(&mut self) { } } // REJECT +LL | impl Drop for Y { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Ca` is mentioned multiple times note: use the same sequence of generic lifetime, type and const parameters as the struct definition - --> $DIR/reject-specialized-drops-8142.rs:18:1 + --> $DIR/reject-specialized-drops-8142.rs:48:1 | LL | struct Y; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:66:14 + --> $DIR/reject-specialized-drops-8142.rs:130:15 | -LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT - | ^^^^^ +LL | impl Drop for Enum { + | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:20:1 + --> $DIR/reject-specialized-drops-8142.rs:50:1 | -LL | enum Enum { Variant(T) } +LL | enum Enum { | ^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:69:14 + --> $DIR/reject-specialized-drops-8142.rs:135:15 | -LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT - | ^^^^^ +LL | impl Drop for TupleStruct { + | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:21:1 + --> $DIR/reject-specialized-drops-8142.rs:53:1 | LL | struct TupleStruct(T); | ^^^^^^^^^^^^^^^^^^^^^ error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not - --> $DIR/reject-specialized-drops-8142.rs:72:21 + --> $DIR/reject-specialized-drops-8142.rs:140:22 | -LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT - | ^^^^^ +LL | impl Drop for Union { + | ^^^^^ | note: the implementor must specify the same requirement - --> $DIR/reject-specialized-drops-8142.rs:22:1 + --> $DIR/reject-specialized-drops-8142.rs:54:1 | -LL | union Union { f: T } +LL | union Union { | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0366, E0367. For more information about an error, try `rustc --explain E0366`. diff --git a/tests/ui/dropck/transitive-outlives.bad.stderr b/tests/ui/dropck/transitive-outlives.bad.stderr index 9ecc4841dce5..5b7968fce80c 100644 --- a/tests/ui/dropck/transitive-outlives.bad.stderr +++ b/tests/ui/dropck/transitive-outlives.bad.stderr @@ -1,8 +1,11 @@ error[E0367]: `Drop` impl requires `'a: 'c` but the struct it is implemented for does not - --> $DIR/transitive-outlives.rs:20:9 + --> $DIR/transitive-outlives.rs:18:1 | -LL | 'a: 'c, - | ^^ +LL | / impl<'a, 'b, 'c> Drop for DropMe<'a, 'b, 'c> +LL | | +LL | | where +LL | | 'a: 'c, + | |___________^ | note: the implementor must specify the same requirement --> $DIR/transitive-outlives.rs:7:1 diff --git a/tests/ui/dropck/transitive-outlives.rs b/tests/ui/dropck/transitive-outlives.rs index e96ac6faae47..37c0a1ff5e27 100644 --- a/tests/ui/dropck/transitive-outlives.rs +++ b/tests/ui/dropck/transitive-outlives.rs @@ -16,9 +16,9 @@ where #[cfg(bad)] impl<'a, 'b, 'c> Drop for DropMe<'a, 'b, 'c> +//[bad]~^ ERROR `Drop` impl requires `'a: 'c` where 'a: 'c, - //[bad]~^ ERROR `Drop` impl requires `'a: 'c` { fn drop(&mut self) {} } diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.rs b/tests/ui/dropck/unconstrained_const_param_on_drop.rs index 369ec7280bd3..de77fa55fb28 100644 --- a/tests/ui/dropck/unconstrained_const_param_on_drop.rs +++ b/tests/ui/dropck/unconstrained_const_param_on_drop.rs @@ -1,8 +1,7 @@ -//@ known-bug: unknown -//@ failure-status: 101 - struct Foo {} impl Drop for Foo {} +//~^ ERROR: `Drop` impl requires `the constant `_` has type `usize`` +//~| ERROR: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates fn main() {} diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr index b48ae8cc8af2..851888534eeb 100644 --- a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr +++ b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr @@ -1,212 +1,17 @@ -thread 'rustc' panicked at compiler/rustc_middle/src/ty/sty.rs:360:36: -called `Option::unwrap()` on a `None` value -stack backtrace: - 0: begin_panic_handler - at ./library/std/src/panicking.rs:661:5 - 1: panic_fmt - at ./library/core/src/panicking.rs:74:14 - 2: panic - at ./library/core/src/panicking.rs:148:5 - 3: core::option::unwrap_failed - at ./library/core/src/option.rs:2013:5 - 4: unwrap - at ./library/core/src/option.rs:963:21 - 5: find_ty_from_env - at ./compiler/rustc_middle/src/ty/sty.rs:360:36 - 6: process_obligation - at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:472:29 - 7: process_obligations - at ./compiler/rustc_data_structures/src/obligation_forest/mod.rs:462:23 - 8: select - at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:107:13 - 9: select_where_possible - at ./compiler/rustc_trait_selection/src/traits/fulfill.rs:160:9 - 10: select_all_or_error, rustc_trait_selection::traits::FulfillmentError> - at ./compiler/rustc_infer/src/traits/engine.rs:82:22 - 11: select_all_or_error - at ./compiler/rustc_trait_selection/src/traits/engine.rs:189:9 - 12: ensure_drop_predicates_are_implied_by_item_defn - at ./compiler/rustc_hir_analysis/src/check/dropck.rs:154:18 - 13: check_drop_impl - at ./compiler/rustc_hir_analysis/src/check/dropck.rs:60:13 - 14: call core::result::Result<(), rustc_span::ErrorGuaranteed>, (rustc_middle::ty::context::TyCtxt, rustc_span::def_id::DefId)> - at ./library/core/src/ops/function.rs:79:5 - 15: {closure#0} core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_middle/src/ty/util.rs:360:16 - 16: for_each_relevant_impl core::result::Result<(), rustc_span::ErrorGuaranteed>>> - at ./compiler/rustc_middle/src/ty/trait_def.rs:166:21 - 17: calculate_dtor core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_middle/src/ty/util.rs:359:9 - 18: rustc_hir_analysis::check::adt_destructor - at ./compiler/rustc_hir_analysis/src/check/mod.rs:125:5 - 19: {closure#0} - at ./compiler/rustc_query_impl/src/plumbing.rs:285:13 - [... omitted 22 frames ...] - 20: query_get_at>> - at ./compiler/rustc_middle/src/query/plumbing.rs:145:17 - 21: adt_destructor - at ./compiler/rustc_middle/src/query/plumbing.rs:423:31 - 22: adt_destructor - at ./compiler/rustc_middle/src/query/plumbing.rs:414:35 - 23: destructor - at ./compiler/rustc_middle/src/ty/adt.rs:610:13 - 24: check_struct - at ./compiler/rustc_hir_analysis/src/check/check.rs:71:5 - 25: check_item_type - at ./compiler/rustc_hir_analysis/src/check/check.rs:730:13 - 26: check_item - at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:335:5 - 27: check_well_formed - at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:192:39 - 28: {closure#0} - at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 - [... omitted 22 frames ...] - 29: query_ensure_error_guaranteed>, ()> - at ./compiler/rustc_middle/src/query/plumbing.rs:181:9 - 30: check_well_formed - at ./compiler/rustc_middle/src/query/plumbing.rs:199:9 - 31: {closure#1} - at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:1995:47 - 32: {closure#0} - at ./compiler/rustc_middle/src/hir/mod.rs:89:57 - 33: {closure#0}<&[rustc_hir::hir::ImplItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_impl_items::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:203:50 - 34: call_once, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure#0}::{closure_env#0}<&[rustc_hir::hir::ImplItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_impl_items::{closure_env#0}>> - at ./library/core/src/panic/unwind_safe.rs:272:9 - 35: do_call>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/std/src/panicking.rs:553:40 - 36: try, core::panic::unwind_safe::AssertUnwindSafe>>> - at ./library/std/src/panicking.rs:517:19 - 37: catch_unwind>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/std/src/panic.rs:350:14 - 38: run, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure#2}::{closure_env#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:28:9 - 39: {closure#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:206:46 - 40: {closure#0}<&rustc_hir::hir::ItemId, core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/core/src/iter/adapters/filter_map.rs:39:28 - 41: fold, core::iter::adapters::filter_map::filter_map_fold::{closure_env#0}<&rustc_hir::hir::ItemId, core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>>> - at ./library/core/src/slice/iter/macros.rs:232:27 - 42: fold, core::slice::iter::Iter, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure#0}::{closure_env#2}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>, fn(core::result::Result<(), rustc_span::ErrorGuaranteed>, core::result::Result<(), rustc_span::ErrorGuaranteed>) -> core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/core/src/iter/adapters/filter_map.rs:148:9 - 43: {closure#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:206:73 - 44: parallel_guard, rustc_data_structures::sync::parallel::enabled::try_par_for_each_in::{closure_env#0}<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:44:15 - 45: try_par_for_each_in<&[rustc_hir::hir::ItemId], rustc_span::ErrorGuaranteed, rustc_middle::hir::{impl#0}::par_items::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:199:9 - 46: par_items - at ./compiler/rustc_middle/src/hir/mod.rs:75:9 - 47: check_mod_type_wf - at ./compiler/rustc_hir_analysis/src/check/wfcheck.rs:1994:19 - 48: {closure#0} - at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 - [... omitted 22 frames ...] - 49: query_ensure_error_guaranteed>, ()> - at ./compiler/rustc_middle/src/query/plumbing.rs:181:9 - 50: check_mod_type_wf - at ./compiler/rustc_middle/src/query/plumbing.rs:199:9 - 51: {closure#0} - at ./compiler/rustc_hir_analysis/src/lib.rs:162:21 - 52: {closure#0} - at ./compiler/rustc_middle/src/hir/map/mod.rs:463:13 - 53: {closure#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:34 - 54: call_once<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#0}::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> - at ./library/core/src/panic/unwind_safe.rs:272:9 - 55: do_call>>, ()> - at ./library/std/src/panicking.rs:553:40 - 56: try<(), core::panic::unwind_safe::AssertUnwindSafe>>> - at ./library/std/src/panicking.rs:517:19 - 57: catch_unwind>>, ()> - at ./library/std/src/panic.rs:350:14 - 58: run<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:28:9 - 59: {closure#1}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:186:21 - 60: for_each>> - at ./library/core/src/slice/iter/macros.rs:254:21 - 61: {closure#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:185:17 - 62: parallel_guard<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in::{closure_env#0}<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:44:15 - 63: par_for_each_in<&rustc_hir::hir_id::OwnerId, &[rustc_hir::hir_id::OwnerId], rustc_middle::hir::map::{impl#3}::par_for_each_module::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:178:9 - 64: par_for_each_module - at ./compiler/rustc_middle/src/hir/map/mod.rs:462:9 - 65: {closure#0} - at ./compiler/rustc_hir_analysis/src/lib.rs:161:9 - 66: run<(), rustc_hir_analysis::check_crate::{closure_env#0}> - at ./compiler/rustc_data_structures/src/profiling.rs:754:9 - 67: time<(), rustc_hir_analysis::check_crate::{closure_env#0}> - at ./compiler/rustc_session/src/utils.rs:16:9 - 68: check_crate - at ./compiler/rustc_hir_analysis/src/lib.rs:160:5 - 69: run_required_analyses - at ./compiler/rustc_interface/src/passes.rs:784:5 - 70: analysis - at ./compiler/rustc_interface/src/passes.rs:823:5 - 71: {closure#0} - at ./compiler/rustc_query_impl/src/plumbing.rs:281:9 - [... omitted 22 frames ...] - 72: query_get_at>> - at ./compiler/rustc_middle/src/query/plumbing.rs:145:17 - 73: analysis - at ./compiler/rustc_middle/src/query/plumbing.rs:423:31 - 74: analysis - at ./compiler/rustc_middle/src/query/plumbing.rs:414:35 - 75: {closure#5} - at ./compiler/rustc_driver_impl/src/lib.rs:445:52 - 76: {closure#1}> - at ./compiler/rustc_middle/src/ty/context.rs:1296:37 - 77: {closure#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_middle/src/ty/context/tls.rs:82:9 - 78: try_with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/std/src/thread/local.rs:283:12 - 79: with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./library/std/src/thread/local.rs:260:9 - 80: enter_context>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_middle/src/ty/context/tls.rs:79:9 - 81: enter> - at ./compiler/rustc_middle/src/ty/context.rs:1296:9 - 82: {closure#1} - at ./compiler/rustc_driver_impl/src/lib.rs:445:13 - 83: enter, rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_interface/src/queries.rs:202:19 - 84: {closure#0} - at ./compiler/rustc_driver_impl/src/lib.rs:389:22 - 85: {closure#1}, rustc_driver_impl::run_compiler::{closure_env#0}> - at ./compiler/rustc_interface/src/interface.rs:502:27 - 86: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_interface/src/util.rs:154:13 - 87: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_interface/src/util.rs:106:21 - 88: set, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at /home/boxy/.cargo/registry/src/index.crates.io-6f17d22bba15001f/scoped-tls-1.0.1/src/lib.rs:137:9 - 89: create_session_globals_then, rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>>> - at ./compiler/rustc_span/src/lib.rs:134:5 - 90: {closure#0}, rustc_driver_impl::run_compiler::{closure_env#0}>, core::result::Result<(), rustc_span::ErrorGuaranteed>>, core::result::Result<(), rustc_span::ErrorGuaranteed>> - at ./compiler/rustc_interface/src/util.rs:105:17 -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. +error[E0367]: `Drop` impl requires `the constant `_` has type `usize`` but the struct it is implemented for does not + --> $DIR/unconstrained_const_param_on_drop.rs:3:6 + | +LL | impl Drop for Foo {} + | ^^^^^^^^^^^^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/unconstrained_const_param_on_drop.rs:1:1 + | +LL | struct Foo {} + | ^^^^^^^^^^ -error: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md - -note: please make sure that you have updated to the latest nightly - -note: rustc 1.81.0-dev running on x86_64-unknown-linux-gnu - -note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/home/boxy/.cargo -Z ignore-directory-in-diagnostics-source-blocks=/media/Nyoomies/Repos/rust/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 - -query stack during panic: -#0 [adt_destructor] computing `Drop` impl for `Foo` -#1 [check_well_formed] checking that `Foo` is well-formed -#2 [check_mod_type_wf] checking that types are well-formed in top-level module -#3 [analysis] running analysis passes on this crate -end of query stack error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates - --> $DIR/unconstrained_const_param_on_drop.rs:6:6 + --> $DIR/unconstrained_const_param_on_drop.rs:3:6 | LL | impl Drop for Foo {} | ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter @@ -214,6 +19,7 @@ LL | impl Drop for Foo {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0367. +For more information about an error, try `rustc --explain E0207`. From e8445818d49fe968b35a130c66071c1b56498f93 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Jun 2024 12:58:35 -0400 Subject: [PATCH 04/49] Reorder modifiers and polarity to be *after* binder in trait bounds --- compiler/rustc_parse/src/parser/ty.rs | 4 +- .../async-fn/higher-ranked-async-fn.rs | 2 +- .../impl-trait/normalize-tait-in-const.stderr | 41 ++----------------- tests/ui/issues/issue-39089.rs | 3 +- tests/ui/issues/issue-39089.stderr | 8 ++++ tests/ui/parser/bounds-type.rs | 2 +- .../tilde-const-syntax.rs | 4 +- 7 files changed, 19 insertions(+), 45 deletions(-) create mode 100644 tests/ui/issues/issue-39089.stderr diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1e5b227aaa9b..24183ac1218e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -978,7 +978,7 @@ impl<'a> Parser<'a> { /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for] SIMPLE_PATH + /// TY_BOUND_NOPAREN = [for] [TRAIT_BOUND_MODIFIERS] SIMPLE_PATH /// ``` /// /// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`. @@ -988,8 +988,8 @@ impl<'a> Parser<'a> { has_parens: bool, leading_token: &Token, ) -> PResult<'a, GenericBound> { - let modifiers = self.parse_trait_bound_modifiers()?; let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?; + let modifiers = self.parse_trait_bound_modifiers()?; // Recover erroneous lifetime bound with modifiers or binder. // e.g. `T: for<'a> 'a` or `T: ~const 'a`. diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs index be338ddeb7db..f8da517213ae 100644 --- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs +++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs @@ -15,7 +15,7 @@ async fn f(arg: &i32) {} async fn func(f: F) where - F: async for<'a> Fn(&'a i32), + F: for<'a> async Fn(&'a i32), { let x: i32 = 0; f(&x).await; diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 73f4d4c38856..77de689fb97a 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,41 +1,8 @@ -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:42 +error: expected a trait, found type + --> $DIR/normalize-tait-in-const.rs:27:34 | LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:27:69 - | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { - | ^^^^^^^^ +error: aborting due to 1 previous error -error[E0015]: cannot call non-const closure in constant functions - --> $DIR/normalize-tait-in-const.rs:28:5 - | -LL | fun(filter_positive()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) { - | ++++++++++++++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | - -error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/normalize-tait-in-const.rs:27:79 - | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { - | ^^^ the destructor for this type cannot be evaluated in constant functions -LL | fun(filter_positive()); -LL | } - | - value is dropped here - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0015, E0493. -For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-39089.rs b/tests/ui/issues/issue-39089.rs index b00b84238023..e6bec3373549 100644 --- a/tests/ui/issues/issue-39089.rs +++ b/tests/ui/issues/issue-39089.rs @@ -1,5 +1,4 @@ -//@ check-pass -#![allow(dead_code)] fn f Sized>() {} +//~^ ERROR expected a trait, found type fn main() {} diff --git a/tests/ui/issues/issue-39089.stderr b/tests/ui/issues/issue-39089.stderr new file mode 100644 index 000000000000..3e57a6fcbcb5 --- /dev/null +++ b/tests/ui/issues/issue-39089.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/issue-39089.rs:1:10 + | +LL | fn f Sized>() {} + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index a1971fa3146d..2b2a44b70628 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -5,7 +5,7 @@ struct S< T: Tr + 'a, // OK T: 'a, // OK T:, // OK - T: ?for<'a> Trait, // OK + T: for<'a> ?Trait, // OK T: Tr +, // OK T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs index 496f97b5e24a..4dd0e69598d7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs @@ -4,6 +4,6 @@ #![feature(const_trait_impl)] struct S< - T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add, - T: ~const ?for<'a: 'b> m::Trait<'a>, + T: for<'a> ~const ?Tr<'a> + 'static + ~const std::ops::Add, + T: for<'a: 'b> ~const ?m::Trait<'a>, >; From 32c8bfdb11e519c6608ead730b6dfafc6cafb9c5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Jun 2024 13:07:03 -0400 Subject: [PATCH 05/49] Improve error message --- compiler/rustc_parse/messages.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 9 ++++ compiler/rustc_parse/src/parser/ty.rs | 8 ++++ src/tools/tidy/src/ui_tests.rs | 2 +- .../ui/impl-trait/normalize-tait-in-const.rs | 2 +- .../impl-trait/normalize-tait-in-const.stderr | 43 ++++++++++++++++--- tests/ui/issues/issue-39089.rs | 2 +- tests/ui/issues/issue-39089.stderr | 8 ++-- 8 files changed, 66 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 02c3c87313bc..5fb59eeb4f32 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -53,6 +53,9 @@ parse_bare_cr = {$double_quotes -> parse_bare_cr_in_raw_string = bare CR not allowed in raw string +parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers + .label = place the `for<...>` binder before any modifiers + parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases parse_box_not_pat = expected pattern, found {$descr} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3ae9b6dad998..6738cc4a1200 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3041,3 +3041,12 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = ")")] pub right: Span, } + +#[derive(Diagnostic)] +#[diag(parse_binder_before_modifiers)] +pub struct BinderBeforeModifiers { + #[primary_span] + pub binder_span: Span, + #[label] + pub modifiers_span: Span, +} diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 24183ac1218e..306029ca94c6 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -989,7 +989,10 @@ impl<'a> Parser<'a> { leading_token: &Token, ) -> PResult<'a, GenericBound> { let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?; + + let modifiers_lo = self.token.span; let modifiers = self.parse_trait_bound_modifiers()?; + let modifiers_span = modifiers_lo.to(self.prev_token.span); // Recover erroneous lifetime bound with modifiers or binder. // e.g. `T: for<'a> 'a` or `T: ~const 'a`. @@ -998,6 +1001,11 @@ impl<'a> Parser<'a> { return self.parse_generic_lt_bound(lo, has_parens); } + if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? { + lifetime_defs.extend(more_lifetime_defs); + self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span }); + } + let mut path = if self.token.is_keyword(kw::Fn) && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) && let Some(path) = self.recover_path_from_fn() diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 5e6992038e39..0ae0356b2c45 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -16,7 +16,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1672; +const ISSUES_ENTRY_LIMIT: u32 = 1673; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs index fc90139d6409..e3f53e5f8a82 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.rs +++ b/tests/ui/impl-trait/normalize-tait-in-const.rs @@ -24,7 +24,7 @@ mod foo { } use foo::*; -const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { +const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { fun(filter_positive()); } diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 77de689fb97a..b20dabe7b25a 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,8 +1,41 @@ -error: expected a trait, found type - --> $DIR/normalize-tait-in-const.rs:27:34 +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/normalize-tait-in-const.rs:27:42 | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/normalize-tait-in-const.rs:27:69 + | +LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^^^^^^ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/normalize-tait-in-const.rs:28:5 + | +LL | fun(filter_positive()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) { + | ++++++++++++++++++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/normalize-tait-in-const.rs:27:79 + | +LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^ the destructor for this type cannot be evaluated in constant functions +LL | fun(filter_positive()); +LL | } + | - value is dropped here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-39089.rs b/tests/ui/issues/issue-39089.rs index e6bec3373549..822c47503afe 100644 --- a/tests/ui/issues/issue-39089.rs +++ b/tests/ui/issues/issue-39089.rs @@ -1,4 +1,4 @@ fn f Sized>() {} -//~^ ERROR expected a trait, found type +//~^ ERROR `for<...>` binder should be placed before trait bound modifiers fn main() {} diff --git a/tests/ui/issues/issue-39089.stderr b/tests/ui/issues/issue-39089.stderr index 3e57a6fcbcb5..a81010aedff5 100644 --- a/tests/ui/issues/issue-39089.stderr +++ b/tests/ui/issues/issue-39089.stderr @@ -1,8 +1,10 @@ -error: expected a trait, found type - --> $DIR/issue-39089.rs:1:10 +error: `for<...>` binder should be placed before trait bound modifiers + --> $DIR/issue-39089.rs:1:13 | LL | fn f Sized>() {} - | ^^^^^^^^^^^^^ + | - ^^^^ + | | + | place the `for<...>` binder before any modifiers error: aborting due to 1 previous error From 898ed2ffa6c485530af1fbe6117c0deb4290715f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Jul 2024 17:49:50 -0400 Subject: [PATCH 06/49] Enforce that ? and for<...> are not combined --- compiler/rustc_parse/messages.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 10 ++++++++++ compiler/rustc_parse/src/parser/ty.rs | 13 +++++++++++++ tests/ui/parser/bounds-type.rs | 2 +- tests/ui/parser/bounds-type.stderr | 10 +++++++++- .../rfc-2632-const-trait-impl/tilde-const-syntax.rs | 4 ++-- 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 5fb59eeb4f32..5b4a5f4dd38e 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -53,6 +53,9 @@ parse_bare_cr = {$double_quotes -> parse_bare_cr_in_raw_string = bare CR not allowed in raw string +parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier + .label = there is not a well-defined meaning for a higher-ranked `{$polarity}` trait + parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers .label = place the `for<...>` binder before any modifiers diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 6738cc4a1200..9b18a771fdea 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3050,3 +3050,13 @@ pub struct BinderBeforeModifiers { #[label] pub modifiers_span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_binder_and_polarity)] +pub struct BinderAndPolarity { + #[primary_span] + pub polarity_span: Span, + #[label] + pub binder_span: Span, + pub polarity: &'static str, +} diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 306029ca94c6..6de778fa9f21 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -994,6 +994,19 @@ impl<'a> Parser<'a> { let modifiers = self.parse_trait_bound_modifiers()?; let modifiers_span = modifiers_lo.to(self.prev_token.span); + if let Some(binder_span) = binder_span { + match modifiers.polarity { + BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => { + self.dcx().emit_err(errors::BinderAndPolarity { + binder_span, + polarity_span, + polarity: modifiers.polarity.as_str(), + }); + } + BoundPolarity::Positive => {} + } + } + // Recover erroneous lifetime bound with modifiers or binder. // e.g. `T: for<'a> 'a` or `T: ~const 'a`. if self.token.is_lifetime() { diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index 2b2a44b70628..47fec7b1e77f 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -5,7 +5,7 @@ struct S< T: Tr + 'a, // OK T: 'a, // OK T:, // OK - T: for<'a> ?Trait, // OK + T: for<'a> ?Trait, //~ ERROR `for<...>` binder not allowed with `?` trait polarity modifier T: Tr +, // OK T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds diff --git a/tests/ui/parser/bounds-type.stderr b/tests/ui/parser/bounds-type.stderr index d1210e88d667..fa8ab6812b15 100644 --- a/tests/ui/parser/bounds-type.stderr +++ b/tests/ui/parser/bounds-type.stderr @@ -1,3 +1,11 @@ +error: `for<...>` binder not allowed with `?` trait polarity modifier + --> $DIR/bounds-type.rs:8:16 + | +LL | T: for<'a> ?Trait, + | ---- ^ + | | + | there is not a well-defined meaning for a higher-ranked `?` trait + error: `?` may only modify trait bounds, not lifetime bounds --> $DIR/bounds-type.rs:10:8 | @@ -16,5 +24,5 @@ error: `const` may only modify trait bounds, not lifetime bounds LL | T: const 'a, | ^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs index 4dd0e69598d7..d65ecae3d067 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs @@ -4,6 +4,6 @@ #![feature(const_trait_impl)] struct S< - T: for<'a> ~const ?Tr<'a> + 'static + ~const std::ops::Add, - T: for<'a: 'b> ~const ?m::Trait<'a>, + T: for<'a> ~const Tr<'a> + 'static + ~const std::ops::Add, + T: for<'a: 'b> ~const m::Trait<'a>, >; From de560c30659281e8c91a48579f907097efe22adf Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 20 Feb 2024 21:40:25 +0100 Subject: [PATCH 07/49] Implement `ambiguous_negative_literals` lint --- compiler/rustc_lint/messages.ftl | 5 + compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint/src/lints.rs | 29 ++++ compiler/rustc_lint/src/precedence.rs | 70 ++++++++++ tests/ui/lint/negative_literals.rs | 35 +++++ tests/ui/lint/negative_literals.stderr | 179 +++++++++++++++++++++++++ 6 files changed, 321 insertions(+) create mode 100644 compiler/rustc_lint/src/precedence.rs create mode 100644 tests/ui/lint/negative_literals.rs create mode 100644 tests/ui/lint/negative_literals.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index f048f6fe8ad4..4f7f01e56b63 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -5,6 +5,11 @@ lint_ambiguous_glob_reexport = ambiguous glob re-exports .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here +lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected + .example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` + .negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal + .current_behavior = add parentheses around the literal and the method call to keep the current behavior + lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 868a44a980a0..0a058b675ffa 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -72,6 +72,7 @@ mod noop_method_call; mod opaque_hidden_inferred_bound; mod pass_by_value; mod passes; +mod precedence; mod ptr_nulls; mod redundant_semicolon; mod reference_casting; @@ -109,6 +110,7 @@ use nonstandard_style::*; use noop_method_call::*; use opaque_hidden_inferred_bound::*; use pass_by_value::*; +use precedence::*; use ptr_nulls::*; use redundant_semicolon::*; use reference_casting::*; @@ -173,6 +175,7 @@ early_lint_methods!( RedundantSemicolons: RedundantSemicolons, UnusedDocComment: UnusedDocComment, Expr2024: Expr2024, + Precedence: Precedence, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 54c73710eca6..873322c13b46 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1489,6 +1489,35 @@ pub struct NonLocalDefinitionsCargoUpdateNote { pub crate_name: Symbol, } +// precedence.rs +#[derive(LintDiagnostic)] +#[diag(lint_ambiguous_negative_literals)] +#[note(lint_example)] +pub struct AmbiguousNegativeLiteralsDiag { + #[subdiagnostic] + pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, + #[subdiagnostic] + pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")] +pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")] +pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + // pass_by_value.rs #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs new file mode 100644 index 000000000000..eb2ba3972779 --- /dev/null +++ b/compiler/rustc_lint/src/precedence.rs @@ -0,0 +1,70 @@ +use rustc_ast::token::LitKind; +use rustc_ast::{Expr, ExprKind, MethodCall, UnOp}; +use rustc_session::{declare_lint, declare_lint_pass}; + +use crate::lints::{ + AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag, + AmbiguousNegativeLiteralsNegativeLiteralSuggestion, +}; +use crate::{EarlyContext, EarlyLintPass, LintContext}; + +declare_lint! { + /// The `ambiguous_negative_literals` lint checks for cases that are + /// confusing between a negative literal and a negation that's not part + /// of the literal. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![allow(unused)] + /// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1 + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Method calls take precedence over unary precedence. Setting the + /// precedence explicitly makes the code clearer and avoid potential bugs. + pub AMBIGUOUS_NEGATIVE_LITERALS, + Deny, + "ambiguous negative literals operations", + report_in_external_macro +} + +declare_lint_pass!(Precedence => [AMBIGUOUS_NEGATIVE_LITERALS]); + +impl EarlyLintPass for Precedence { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind else { + return; + }; + + let mut arg = operand; + let mut at_least_one = false; + while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind { + at_least_one = true; + arg = receiver; + } + + if at_least_one + && let ExprKind::Lit(lit) = &arg.kind + && let LitKind::Integer | LitKind::Float = &lit.kind + { + cx.emit_span_lint( + AMBIGUOUS_NEGATIVE_LITERALS, + expr.span, + AmbiguousNegativeLiteralsDiag { + negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion { + start_span: expr.span.shrink_to_lo(), + end_span: arg.span.shrink_to_hi(), + }, + current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { + start_span: operand.span.shrink_to_lo(), + end_span: operand.span.shrink_to_hi(), + }, + }, + ); + } + } +} diff --git a/tests/ui/lint/negative_literals.rs b/tests/ui/lint/negative_literals.rs new file mode 100644 index 000000000000..048fcd6ff57b --- /dev/null +++ b/tests/ui/lint/negative_literals.rs @@ -0,0 +1,35 @@ +//@ check-fail + +fn main() { + let _ = -1i32.abs(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f32.abs(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f64.asin(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f64.asinh(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f64.tan(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f64.tanh(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1.0_f64.cos().cos(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1.0_f64.cos().sin(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1.0_f64.sin().cos(); + //~^ ERROR `-` has lower precedence than method calls + let _ = -1f64.sin().sin(); + //~^ ERROR `-` has lower precedence than method calls + + dbg!( -1.0_f32.cos() ); + //~^ ERROR `-` has lower precedence than method calls + + // should not warn + let _ = (-1i32).abs(); + let _ = (-1f32).abs(); + let _ = -(1i32).abs(); + let _ = -(1f32).abs(); + let _ = -(1i32.abs()); + let _ = -(1f32.abs()); +} diff --git a/tests/ui/lint/negative_literals.stderr b/tests/ui/lint/negative_literals.stderr new file mode 100644 index 000000000000..df000a718825 --- /dev/null +++ b/tests/ui/lint/negative_literals.stderr @@ -0,0 +1,179 @@ +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:4:13 + | +LL | let _ = -1i32.abs(); + | ^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` + = note: `#[deny(ambiguous_negative_literals)]` on by default +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1i32).abs(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1i32.abs()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:6:13 + | +LL | let _ = -1f32.abs(); + | ^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f32).abs(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f32.abs()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:8:13 + | +LL | let _ = -1f64.asin(); + | ^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f64).asin(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f64.asin()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:10:13 + | +LL | let _ = -1f64.asinh(); + | ^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f64).asinh(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f64.asinh()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:12:13 + | +LL | let _ = -1f64.tan(); + | ^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f64).tan(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f64.tan()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:14:13 + | +LL | let _ = -1f64.tanh(); + | ^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f64).tanh(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f64.tanh()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:16:13 + | +LL | let _ = -1.0_f64.cos().cos(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1.0_f64).cos().cos(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1.0_f64.cos().cos()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:18:13 + | +LL | let _ = -1.0_f64.cos().sin(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1.0_f64).cos().sin(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1.0_f64.cos().sin()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:20:13 + | +LL | let _ = -1.0_f64.sin().cos(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1.0_f64).sin().cos(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1.0_f64.sin().cos()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:22:13 + | +LL | let _ = -1f64.sin().sin(); + | ^^^^^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | let _ = (-1f64).sin().sin(); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | let _ = -(1f64.sin().sin()); + | + + + +error: `-` has lower precedence than method calls, which might be unexpected + --> $DIR/negative_literals.rs:25:11 + | +LL | dbg!( -1.0_f32.cos() ); + | ^^^^^^^^^^^^^^ + | + = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` +help: add parentheses around the `-` and the literal to call the method on a negative literal + | +LL | dbg!( (-1.0_f32).cos() ); + | + + +help: add parentheses around the literal and the method call to keep the current behavior + | +LL | dbg!( -(1.0_f32.cos()) ); + | + + + +error: aborting due to 11 previous errors + From c5e1a12efc32b4e487a8899b143909e17d864adf Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 20 Feb 2024 22:19:26 +0100 Subject: [PATCH 08/49] Remove unary neg from `clippy::precedence` lint --- .../clippy/clippy_lints/src/precedence.rs | 56 +------------------ src/tools/clippy/tests/ui/precedence.fixed | 34 ----------- src/tools/clippy/tests/ui/precedence.rs | 34 ----------- src/tools/clippy/tests/ui/precedence.stderr | 32 +---------- .../clippy/tests/ui/unnecessary_cast.fixed | 2 +- src/tools/clippy/tests/ui/unnecessary_cast.rs | 2 +- 6 files changed, 4 insertions(+), 156 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs index ff83725da691..37f5dd5583bf 100644 --- a/src/tools/clippy/clippy_lints/src/precedence.rs +++ b/src/tools/clippy/clippy_lints/src/precedence.rs @@ -1,38 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp}; -use rustc_ast::token; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; -const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [ - "asin", - "asinh", - "atan", - "atanh", - "cbrt", - "fract", - "round", - "signum", - "sin", - "sinh", - "tan", - "tanh", - "to_degrees", - "to_radians", -]; - declare_clippy_lint! { /// ### What it does /// Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: /// * mixed usage of arithmetic and bit shifting/combining operators without /// parentheses - /// * a "negative" numeric literal (which is really a unary `-` followed by a - /// numeric literal) - /// followed by a method call /// /// ### Why is this bad? /// Not everyone knows the precedence of those operators by @@ -41,7 +20,6 @@ declare_clippy_lint! { /// /// ### Example /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 - /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 #[clippy::version = "pre 1.29.0"] pub PRECEDENCE, complexity, @@ -104,38 +82,6 @@ impl EarlyLintPass for Precedence { (false, false) => (), } } - - if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind { - let mut arg = operand; - - let mut all_odd = true; - while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind { - let seg_str = seg.ident.name.as_str(); - all_odd &= ALLOWED_ODD_FUNCTIONS - .iter() - .any(|odd_function| **odd_function == *seg_str); - arg = receiver; - } - - if !all_odd - && let ExprKind::Lit(lit) = &arg.kind - && let token::LitKind::Integer | token::LitKind::Float = &lit.kind - { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!( - "-({})", - snippet_with_applicability(cx, operand.span, "..", &mut applicability) - ), - applicability, - ); - } - } } } diff --git a/src/tools/clippy/tests/ui/precedence.fixed b/src/tools/clippy/tests/ui/precedence.fixed index cc87de0d90f1..c25c2062aceb 100644 --- a/src/tools/clippy/tests/ui/precedence.fixed +++ b/src/tools/clippy/tests/ui/precedence.fixed @@ -20,40 +20,6 @@ fn main() { 1 ^ (1 - 1); 3 | (2 - 1); 3 & (5 - 2); - -(1i32.abs()); - -(1f32.abs()); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -(1.0_f64.cos().cos()); - let _ = -(1.0_f64.cos().sin()); - let _ = -(1.0_f64.sin().cos()); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); let b = 3; trip!(b * 8); diff --git a/src/tools/clippy/tests/ui/precedence.rs b/src/tools/clippy/tests/ui/precedence.rs index 00c18d92b5fb..dc242ecf4c72 100644 --- a/src/tools/clippy/tests/ui/precedence.rs +++ b/src/tools/clippy/tests/ui/precedence.rs @@ -20,40 +20,6 @@ fn main() { 1 ^ 1 - 1; 3 | 2 - 1; 3 & 5 - 2; - -1i32.abs(); - -1f32.abs(); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -1.0_f64.cos().cos(); - let _ = -1.0_f64.cos().sin(); - let _ = -1.0_f64.sin().cos(); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); let b = 3; trip!(b * 8); diff --git a/src/tools/clippy/tests/ui/precedence.stderr b/src/tools/clippy/tests/ui/precedence.stderr index 47e61326219d..8057c25a5e49 100644 --- a/src/tools/clippy/tests/ui/precedence.stderr +++ b/src/tools/clippy/tests/ui/precedence.stderr @@ -43,35 +43,5 @@ error: operator precedence can trip the unwary LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:23:5 - | -LL | -1i32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:24:5 - | -LL | -1f32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:51:13 - | -LL | let _ = -1.0_f64.cos().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().cos())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:52:13 - | -LL | let _ = -1.0_f64.cos().sin(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().sin())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:53:13 - | -LL | let _ = -1.0_f64.sin().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.sin().cos())` - -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed index 288541362cdd..c43e50761bd5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed @@ -206,7 +206,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0_f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_negative_literals)] let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs index eef3a42e3514..4a5ca231315e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_cast.rs +++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs @@ -206,7 +206,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0 as f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_negative_literals)] let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } From de88bc5c8921774681ecac0a5249b370a9768a6c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Jul 2024 18:06:44 -0400 Subject: [PATCH 09/49] And additionally enforce ? and async/const aren't mixed --- compiler/rustc_ast_passes/messages.ftl | 2 - .../rustc_ast_passes/src/ast_validation.rs | 11 ----- compiler/rustc_ast_passes/src/errors.rs | 9 ---- compiler/rustc_parse/messages.ftl | 3 ++ compiler/rustc_parse/src/errors.rs | 11 +++++ compiler/rustc_parse/src/parser/ty.rs | 29 ++++++++++++ tests/ui/parser/bounds-type.rs | 13 +++++- tests/ui/parser/bounds-type.stderr | 46 +++++++++++++++++-- ...utually-exclusive-trait-bound-modifiers.rs | 8 ++-- ...lly-exclusive-trait-bound-modifiers.stderr | 32 ++++++++----- 10 files changed, 120 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 7da726ef4086..0408f6ad5435 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -152,8 +152,6 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed .help = remove one of these features -ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive - ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} .because = {$annotation} because of this .type = inherent impl for this type diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dd0d904c52cc..8041b89abe25 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1435,17 +1435,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }; self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); } - ( - _, - BoundConstness::Always(_) | BoundConstness::Maybe(_), - BoundPolarity::Negative(_) | BoundPolarity::Maybe(_), - ) => { - self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers { - span: bound.span(), - left: modifiers.constness.as_str(), - right: modifiers.polarity.as_str(), - }); - } _ => {} } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index bfb904764501..51f80b9ad4ac 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -657,15 +657,6 @@ pub enum TildeConstReason { Item, } -#[derive(Diagnostic)] -#[diag(ast_passes_incompatible_trait_bound_modifiers)] -pub struct IncompatibleTraitBoundModifiers { - #[primary_span] - pub span: Span, - pub left: &'static str, - pub right: &'static str, -} - #[derive(Diagnostic)] #[diag(ast_passes_const_and_async)] pub struct ConstAndAsync { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 5b4a5f4dd38e..f0cdb6c63a49 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -575,6 +575,9 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds .suggestion = remove the `{$modifier}` +parse_modifiers_and_polarity = `{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier + .label = there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait + parse_more_than_one_char = character literal may only contain one codepoint .followed_by = this `{$chr}` is followed by the combining {$len -> [one] mark diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9b18a771fdea..75417885d2af 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3060,3 +3060,14 @@ pub struct BinderAndPolarity { pub binder_span: Span, pub polarity: &'static str, } + +#[derive(Diagnostic)] +#[diag(parse_modifiers_and_polarity)] +pub struct PolarityAndModifiers { + #[primary_span] + pub polarity_span: Span, + #[label] + pub modifiers_span: Span, + pub polarity: &'static str, + pub modifiers_concatenated: String, +} diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6de778fa9f21..a2db4b6feef7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -930,6 +930,7 @@ impl<'a> Parser<'a> { /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"] /// ``` fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { + let modifier_lo = self.token.span; let constness = if self.eat(&token::Tilde) { let tilde = self.prev_token.span; self.expect_keyword(kw::Const)?; @@ -962,6 +963,7 @@ impl<'a> Parser<'a> { } else { BoundAsyncness::Normal }; + let modifier_hi = self.prev_token.span; let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) @@ -972,6 +974,33 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; + // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`. + match polarity { + BoundPolarity::Positive => { + // All trait bound modifiers allowed to combine with positive polarity + } + BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => { + match (asyncness, constness) { + (BoundAsyncness::Normal, BoundConstness::Never) => { + // Ok, no modifiers. + } + (_, _) => { + let constness = constness.as_str(); + let asyncness = asyncness.as_str(); + let glue = + if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" }; + let modifiers_concatenated = format!("{constness}{glue}{asyncness}"); + self.dcx().emit_err(errors::PolarityAndModifiers { + polarity_span, + polarity: polarity.as_str(), + modifiers_span: modifier_lo.to(modifier_hi), + modifiers_concatenated, + }); + } + } + } + } + Ok(TraitBoundModifiers { constness, asyncness, polarity }) } diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index 47fec7b1e77f..7cee6def32f8 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Z parse-only +//@ edition: 2021 struct S< T: 'a + Tr, // OK @@ -10,10 +11,20 @@ struct S< T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds T: ~const Tr, // OK - T: ~const ?Tr, // OK + T: ~const ?Tr, //~ ERROR `~const` trait not allowed with `?` trait polarity modifier T: ~const Tr + 'a, // OK T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds T: const 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds + + T: async Tr, // OK + T: async ?Tr, //~ ERROR `async` trait not allowed with `?` trait polarity modifier + T: async Tr + 'a, // OK + T: async 'a, //~ ERROR `async` may only modify trait bounds, not lifetime bounds + + T: const async Tr, // OK + T: const async ?Tr, //~ ERROR `const async` trait not allowed with `?` trait polarity modifier + T: const async Tr + 'a, // OK + T: const async 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds >; fn main() {} diff --git a/tests/ui/parser/bounds-type.stderr b/tests/ui/parser/bounds-type.stderr index fa8ab6812b15..09c35c12b000 100644 --- a/tests/ui/parser/bounds-type.stderr +++ b/tests/ui/parser/bounds-type.stderr @@ -1,5 +1,5 @@ error: `for<...>` binder not allowed with `?` trait polarity modifier - --> $DIR/bounds-type.rs:8:16 + --> $DIR/bounds-type.rs:9:16 | LL | T: for<'a> ?Trait, | ---- ^ @@ -7,22 +7,58 @@ LL | T: for<'a> ?Trait, | there is not a well-defined meaning for a higher-ranked `?` trait error: `?` may only modify trait bounds, not lifetime bounds - --> $DIR/bounds-type.rs:10:8 + --> $DIR/bounds-type.rs:11:8 | LL | T: ?'a, | ^ +error: `~const` trait not allowed with `?` trait polarity modifier + --> $DIR/bounds-type.rs:14:15 + | +LL | T: ~const ?Tr, + | ------ ^ + | | + | there is not a well-defined meaning for a `~const ?` trait + error: `~const` may only modify trait bounds, not lifetime bounds - --> $DIR/bounds-type.rs:15:8 + --> $DIR/bounds-type.rs:16:8 | LL | T: ~const 'a, | ^^^^^^ error: `const` may only modify trait bounds, not lifetime bounds - --> $DIR/bounds-type.rs:16:8 + --> $DIR/bounds-type.rs:17:8 | LL | T: const 'a, | ^^^^^ -error: aborting due to 4 previous errors +error: `async` trait not allowed with `?` trait polarity modifier + --> $DIR/bounds-type.rs:20:14 + | +LL | T: async ?Tr, + | ----- ^ + | | + | there is not a well-defined meaning for a `async ?` trait + +error: `async` may only modify trait bounds, not lifetime bounds + --> $DIR/bounds-type.rs:22:8 + | +LL | T: async 'a, + | ^^^^^ + +error: `const async` trait not allowed with `?` trait polarity modifier + --> $DIR/bounds-type.rs:25:20 + | +LL | T: const async ?Tr, + | ----------- ^ + | | + | there is not a well-defined meaning for a `const async ?` trait + +error: `const` may only modify trait bounds, not lifetime bounds + --> $DIR/bounds-type.rs:27:8 + | +LL | T: const async 'a, + | ^^^^^ + +error: aborting due to 9 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs index 37e285f2c659..aaab8e819a39 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs @@ -1,17 +1,17 @@ #![feature(const_trait_impl)] const fn maybe_const_maybe() {} -//~^ ERROR `~const` and `?` are mutually exclusive +//~^ ERROR `~const` trait not allowed with `?` trait polarity modifier fn const_maybe() {} -//~^ ERROR `const` and `?` are mutually exclusive +//~^ ERROR `const` trait not allowed with `?` trait polarity modifier const fn maybe_const_negative() {} -//~^ ERROR `~const` and `!` are mutually exclusive +//~^ ERROR `~const` trait not allowed with `!` trait polarity modifier //~| ERROR negative bounds are not supported fn const_negative() {} -//~^ ERROR `const` and `!` are mutually exclusive +//~^ ERROR `const` trait not allowed with `!` trait polarity modifier //~| ERROR negative bounds are not supported #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr index 1938f740170b..18e4d160f5f4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr @@ -1,26 +1,34 @@ -error: `~const` and `?` are mutually exclusive - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31 +error: `~const` trait not allowed with `?` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:38 | LL | const fn maybe_const_maybe() {} - | ^^^^^^^^^^^^^ + | ------ ^ + | | + | there is not a well-defined meaning for a `~const ?` trait -error: `const` and `?` are mutually exclusive - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:19 +error: `const` trait not allowed with `?` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:25 | LL | fn const_maybe() {} - | ^^^^^^^^^^^^ + | ----- ^ + | | + | there is not a well-defined meaning for a `const ?` trait -error: `~const` and `!` are mutually exclusive - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:34 +error: `~const` trait not allowed with `!` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41 | LL | const fn maybe_const_negative() {} - | ^^^^^^^^^^^^^ + | ------ ^ + | | + | there is not a well-defined meaning for a `~const !` trait -error: `const` and `!` are mutually exclusive - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:22 +error: `const` trait not allowed with `!` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 | LL | fn const_negative() {} - | ^^^^^^^^^^^^ + | ----- ^ + | | + | there is not a well-defined meaning for a `const !` trait error: negative bounds are not supported --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41 From 79d1ac66a8317083bb801a5b09ed180dacc8f70c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 21:59:28 -0400 Subject: [PATCH 10/49] Remove rustdoc tests which no longer parse --- src/tools/rustfmt/tests/source/type.rs | 2 -- src/tools/rustfmt/tests/target/negative-bounds.rs | 6 ------ src/tools/rustfmt/tests/target/type.rs | 2 -- 3 files changed, 10 deletions(-) diff --git a/src/tools/rustfmt/tests/source/type.rs b/src/tools/rustfmt/tests/source/type.rs index 61ef73a3cab1..7a232f85198a 100644 --- a/src/tools/rustfmt/tests/source/type.rs +++ b/src/tools/rustfmt/tests/source/type.rs @@ -146,8 +146,6 @@ trait T: ~ const Super {} const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); - impl ~ const T {} fn apit(_: impl ~ const T) {} diff --git a/src/tools/rustfmt/tests/target/negative-bounds.rs b/src/tools/rustfmt/tests/target/negative-bounds.rs index 4fb35cccf668..9fcb86ef4a42 100644 --- a/src/tools/rustfmt/tests/target/negative-bounds.rs +++ b/src/tools/rustfmt/tests/target/negative-bounds.rs @@ -3,9 +3,3 @@ where i32: !Copy, { } - -fn maybe_const_negative() -where - i32: ~const !Copy, -{ -} diff --git a/src/tools/rustfmt/tests/target/type.rs b/src/tools/rustfmt/tests/target/type.rs index c789ecb055a7..325adb52f3f9 100644 --- a/src/tools/rustfmt/tests/target/type.rs +++ b/src/tools/rustfmt/tests/target/type.rs @@ -153,8 +153,6 @@ const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); - impl ~const T {} fn apit(_: impl ~const T) {} From fd16a0efeb3ae37960daeb9d5bd3600a1632c16f Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 27 Jun 2024 01:29:49 +0300 Subject: [PATCH 11/49] rustc_middle: derivative -> derive-where --- Cargo.lock | 13 ++++++++++++- compiler/rustc_middle/Cargo.toml | 2 +- compiler/rustc_middle/src/mir/query.rs | 13 ++++--------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eba4eed3686b..66007b2b6fef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1057,6 +1057,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "derive_builder" version = "0.20.0" @@ -4348,7 +4359,7 @@ name = "rustc_middle" version = "0.0.0" dependencies = [ "bitflags 2.5.0", - "derivative", + "derive-where", "either", "field-offset", "gsgdt", diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 3dc592980fdb..30f26d563ad3 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -derivative = "2.2.0" +derive-where = "1.2.7" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index cd8e28522ecf..acf4414c4d6f 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -2,6 +2,7 @@ use crate::mir; use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt}; +use derive_where::derive_where; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; @@ -224,13 +225,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] -#[derive(derivative::Derivative)] -#[derivative( - PartialOrd, - Ord, - PartialOrd = "feature_allow_slow_enum", - Ord = "feature_allow_slow_enum" -)] +#[derive_where(PartialOrd, Ord)] pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, @@ -240,7 +235,7 @@ pub enum ConstraintCategory<'tcx> { Cast { /// Whether this is an unsizing cast and if yes, this contains the target type. /// Region variables are erased to ReErased. - #[derivative(PartialOrd = "ignore", Ord = "ignore")] + #[derive_where(skip)] unsize_to: Option>, }, @@ -250,7 +245,7 @@ pub enum ConstraintCategory<'tcx> { ClosureBounds, /// Contains the function type if available. - CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option>), + CallArgument(#[derive_where(skip)] Option>), CopyBound, SizedBound, Assignment, From 35ba700d5e091f7f36e1961792c9582ca384d622 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 27 Jun 2024 01:39:48 +0300 Subject: [PATCH 12/49] rustc_span: derivative -> derive-where --- Cargo.lock | 2 +- compiler/rustc_span/Cargo.toml | 2 +- compiler/rustc_span/src/lib.rs | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66007b2b6fef..43010908fb01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4738,7 +4738,7 @@ dependencies = [ name = "rustc_span" version = "0.0.0" dependencies = [ - "derivative", + "derive-where", "indexmap", "itoa", "md-5", diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 83a554fe31de..3fdfe77ead97 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -derivative = "2.2.0" +derive-where = "1.2.7" indexmap = { version = "2.0.0" } itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 266956d63d71..ba3ddab98429 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -38,6 +38,7 @@ // this crate without this line making `rustc_span` available. extern crate self as rustc_span; +use derive_where::derive_where; use rustc_data_structures::{outline, AtomicRef}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; @@ -467,18 +468,18 @@ impl FileName { /// `SpanData` is public because `Span` uses a thread-local interner and can't be /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq, derivative::Derivative)] -#[derivative(PartialOrd, Ord)] +#[derive(Clone, Copy, Hash, PartialEq, Eq)] +#[derive_where(PartialOrd, Ord)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. - #[derivative(PartialOrd = "ignore", Ord = "ignore")] + #[derive_where(skip)] // `SyntaxContext` does not implement `Ord`. // The other fields are enough to determine in-file order. pub ctxt: SyntaxContext, - #[derivative(PartialOrd = "ignore", Ord = "ignore")] + #[derive_where(skip)] // `LocalDefId` does not implement `Ord`. // The other fields are enough to determine in-file order. pub parent: Option, From 70a11c7ba9d486fdf429dc50770db2dbc37b9eed Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 27 Jun 2024 01:59:30 +0300 Subject: [PATCH 13/49] rustc_next_trait_solver: derivative -> derive-where --- Cargo.lock | 2 +- compiler/rustc_next_trait_solver/Cargo.toml | 2 +- .../rustc_next_trait_solver/src/coherence.rs | 7 +++--- .../src/solve/assembly/mod.rs | 4 ++-- .../src/solve/assembly/structural_traits.rs | 4 ++-- .../src/solve/eval_ctxt/mod.rs | 4 ++-- .../src/solve/inspect/build.rs | 22 +++++++------------ 7 files changed, 19 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43010908fb01..e5b19ed5b557 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4488,7 +4488,7 @@ name = "rustc_next_trait_solver" version = "0.0.0" dependencies = [ "bitflags 2.5.0", - "derivative", + "derive-where", "rustc_ast_ir", "rustc_data_structures", "rustc_index", diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 07cd4ae68d9a..cb0730e86739 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -derivative = "2.2.0" +derive-where = "1.2.7" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 55f602d907bb..f22ea41c5122 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use std::ops::ControlFlow; +use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; @@ -108,15 +109,13 @@ impl From for IsFirstInputType { } } -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = "T: Debug"))] +#[derive_where(Debug; I: Interner, T: Debug)] pub enum OrphanCheckErr { NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>), UncoveredTyParams(UncoveredTyParams), } -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = "T: Debug"))] +#[derive_where(Debug; I: Interner, T: Debug)] pub struct UncoveredTyParams { pub uncovered: T, pub local_ty: Option, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 01dde9ca587c..f74597fcb391 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -2,6 +2,7 @@ pub(super) mod structural_traits; +use derive_where::derive_where; use rustc_type_ir::elaborate; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; @@ -21,8 +22,7 @@ use crate::solve::{ /// /// It consists of both the `source`, which describes how that goal would be proven, /// and the `result` when using the given `source`. -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""))] +#[derive_where(Clone, Debug; I: Interner)] pub(super) struct Candidate { pub(super) source: CandidateSource, pub(super) result: CanonicalResponse, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 7df14e81ab5d..770ac9a929ea 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -1,6 +1,7 @@ //! Code which is used by built-in goals that match "structurally", such a auto //! traits, `Copy`/`Clone`. +use derive_where::derive_where; use rustc_ast_ir::{Movability, Mutability}; use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -384,8 +385,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { pub tupled_inputs_ty: I::Ty, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c23bc8f09ad1..e328284c0010 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1,5 +1,6 @@ use std::ops::ControlFlow; +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir::data_structures::ensure_sufficient_stack; @@ -87,8 +88,7 @@ where pub(super) inspect: ProofTreeBuilder, } -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Debug(bound = ""), Default(bound = ""))] +#[derive_where(Clone, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] // FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate. diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index 3e266ddac71f..36e13cc97d64 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; use std::mem; +use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, search_graph, Interner}; @@ -51,8 +52,7 @@ where /// in the code, only one or two variants are actually possible. /// /// We simply ICE in case that assumption is broken. -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""))] +#[derive_where(Debug; I: Interner)] enum DebugSolver { Root, GoalEvaluation(WipGoalEvaluation), @@ -78,8 +78,7 @@ impl From> for DebugSolver { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] struct WipGoalEvaluation { pub uncanonicalized_goal: Goal, pub orig_values: Vec, @@ -96,8 +95,7 @@ impl WipGoalEvaluation { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""))] +#[derive_where(PartialEq, Eq; I: Interner)] pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { Overflow, CycleInStack, @@ -118,8 +116,7 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] struct WipCanonicalGoalEvaluation { goal: CanonicalInput, kind: Option>, @@ -153,8 +150,7 @@ impl WipCanonicalGoalEvaluation { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] struct WipCanonicalGoalEvaluationStep { /// Unlike `EvalCtxt::var_values`, we append a new /// generic arg here whenever we create a new inference @@ -193,8 +189,7 @@ impl WipCanonicalGoalEvaluationStep { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] struct WipProbe { initial_num_var_values: usize, steps: Vec>, @@ -212,8 +207,7 @@ impl WipProbe { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] enum WipProbeStep { AddGoal(GoalSource, inspect::CanonicalState>), NestedProbe(WipProbe), From 168096f663c3268e462c7b9cbe4dd243eb1ded37 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 27 Jun 2024 14:55:44 +0300 Subject: [PATCH 14/49] rustc_type_ir: derivative -> derive-where --- Cargo.lock | 13 +- compiler/rustc_type_ir/Cargo.toml | 2 +- compiler/rustc_type_ir/src/binder.rs | 37 +++--- compiler/rustc_type_ir/src/canonical.rs | 39 ++---- compiler/rustc_type_ir/src/const_kind.rs | 13 +- compiler/rustc_type_ir/src/error.rs | 10 +- compiler/rustc_type_ir/src/generic_arg.rs | 19 +-- compiler/rustc_type_ir/src/opaque_ty.rs | 11 +- compiler/rustc_type_ir/src/outlives.rs | 4 +- compiler/rustc_type_ir/src/predicate.rs | 112 +++--------------- compiler/rustc_type_ir/src/predicate_kind.rs | 13 +- compiler/rustc_type_ir/src/region_kind.rs | 4 +- compiler/rustc_type_ir/src/relate.rs | 13 +- .../src/search_graph/global_cache.rs | 15 +-- .../rustc_type_ir/src/search_graph/mod.rs | 7 +- compiler/rustc_type_ir/src/solve/inspect.rs | 44 +++---- compiler/rustc_type_ir/src/solve/mod.rs | 84 +++---------- compiler/rustc_type_ir/src/ty_kind.rs | 36 ++---- compiler/rustc_type_ir/src/ty_kind/closure.rs | 51 +------- tests/ui/attributes/dump-preds.stderr | 2 +- .../occurs-check/associated-type.next.stderr | 8 +- .../occurs-check/associated-type.old.stderr | 16 +-- .../structually-relate-aliases.stderr | 4 +- .../issue-118950-root-region.stderr | 8 +- 24 files changed, 140 insertions(+), 425 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5b19ed5b557..3f3daa6e103b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1046,17 +1046,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive-where" version = "1.2.7" @@ -4878,7 +4867,7 @@ name = "rustc_type_ir" version = "0.0.0" dependencies = [ "bitflags 2.5.0", - "derivative", + "derive-where", "indexmap", "rustc_ast_ir", "rustc_data_structures", diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index e4bf6069caf3..e20a9e27bbe5 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -derivative = "2.2.0" +derive-where = "1.2.7" indexmap = "2.0.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 2531219baecc..20600fce4c39 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -3,6 +3,7 @@ use std::hash::Hash; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; #[cfg(feature = "nightly")] @@ -25,15 +26,12 @@ use crate::{self as ty, Interner}; /// e.g., `liberate_late_bound_regions`). /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "T: Clone"), - Copy(bound = "T: Copy"), - Hash(bound = "T: Hash"), - PartialEq(bound = "T: PartialEq"), - Eq(bound = "T: Eq"), - Debug(bound = "T: Debug") -)] +#[derive_where(Clone; I: Interner, T: Clone)] +#[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Hash; I: Interner, T: Hash)] +#[derive_where(PartialEq; I: Interner, T: PartialEq)] +#[derive_where(Eq; I: Interner, T: Eq)] +#[derive_where(Debug; I: Interner, T: Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct Binder { value: T, @@ -351,21 +349,18 @@ impl TypeVisitor for ValidateBoundVars { /// /// If you don't have anything to `instantiate`, you may be looking for /// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "T: Clone"), - Copy(bound = "T: Copy"), - PartialEq(bound = "T: PartialEq"), - Eq(bound = "T: Eq"), - Ord(bound = "T: Ord"), - PartialOrd(bound = "T: Ord"), - Hash(bound = "T: Hash"), - Debug(bound = "T: Debug") -)] +#[derive_where(Clone; I: Interner, T: Clone)] +#[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(PartialEq; I: Interner, T: PartialEq)] +#[derive_where(Eq; I: Interner, T: Eq)] +#[derive_where(Ord; I: Interner, T: Ord)] +#[derive_where(PartialOrd; I: Interner, T: Ord)] +#[derive_where(Hash; I: Interner, T: Hash)] +#[derive_where(Debug; I: Interner, T: Debug)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct EarlyBinder { value: T, - #[derivative(Debug = "ignore")] + #[derive_where(skip(Debug))] _tcx: PhantomData, } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 7b114f565f29..4e46a3a13aa5 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; @@ -11,15 +12,12 @@ use crate::{self as ty, Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "V: Clone"), - Hash(bound = "V: Hash"), - PartialEq(bound = "V: PartialEq"), - Eq(bound = "V: Eq"), - Debug(bound = "V: fmt::Debug"), - Copy(bound = "V: Copy") -)] +#[derive_where(Clone; I: Interner, V: Clone)] +#[derive_where(Hash; I: Interner, V: Hash)] +#[derive_where(PartialEq; I: Interner, V: PartialEq)] +#[derive_where(Eq; I: Interner, V: Eq)] +#[derive_where(Debug; I: Interner, V: fmt::Debug)] +#[derive_where(Copy; I: Interner, V: Copy)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct Canonical { @@ -84,15 +82,7 @@ impl fmt::Display for Canonical { /// canonical value. This is sufficient information for code to create /// a copy of the canonical value in some other inference context, /// with fresh inference variables replacing the canonical values. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - Debug(bound = ""), - Eq(bound = ""), - PartialEq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct CanonicalVarInfo { @@ -149,8 +139,7 @@ impl CanonicalVarInfo { /// Describes the "kind" of the canonical variable. This is a "kind" /// in the type-theory sense of the term -- i.e., a "meta" type system /// that analyzes type-like values. -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive_where(Clone, Copy, Hash, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum CanonicalVarKind { @@ -266,15 +255,7 @@ pub enum CanonicalTyVarKind { /// vectors with the original values that were replaced by canonical /// variables. You will need to supply it later to instantiate the /// canonicalized query response. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Hash(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct CanonicalVarValues { diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index f1683f5449f5..dab2d3bf695c 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -10,8 +11,7 @@ use crate::{self as ty, DebruijnIndex, Interner}; use self::ConstKind::*; /// Represents a constant in Rust. -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] +#[derive_where(Clone, Copy, Hash, Eq; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ConstKind { /// A const generic parameter. @@ -79,14 +79,7 @@ impl fmt::Debug for ConstKind { } /// An unevaluated (potentially generic) constant used in the type-system. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct UnevaluatedConst { diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 8b59e9a6f481..8a6d37b7d23f 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::NoSolution; @@ -21,14 +22,7 @@ impl ExpectedFound { } // Data structures used in type unification -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic)] #[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum TypeError { diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index b158f0f5eee9..008268c3bffa 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -1,16 +1,10 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use crate::Interner; -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Debug(bound = ""), - Eq(bound = ""), - PartialEq(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum GenericArgKind { Lifetime(I::Region), @@ -18,14 +12,7 @@ pub enum GenericArgKind { Const(I::Const), } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Debug(bound = ""), - Eq(bound = ""), - PartialEq(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum TermKind { Ty(I::Ty), diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs index d8ed4770e2dc..8fcb9e508a2b 100644 --- a/compiler/rustc_type_ir/src/opaque_ty.rs +++ b/compiler/rustc_type_ir/src/opaque_ty.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; @@ -5,15 +6,7 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; use crate::{self as ty, Interner}; -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = ""), - Copy(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct OpaqueTypeKey { diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 10b6f3355d92..1dd37377085c 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -2,6 +2,7 @@ //! refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that //! RFC for reference. +use derive_where::derive_where; use smallvec::{smallvec, SmallVec}; use crate::data_structures::SsoHashSet; @@ -9,8 +10,7 @@ use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, TypeVisitor}; use crate::{self as ty, Interner}; -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""))] +#[derive_where(Debug; I: Interner)] pub enum Component { Region(I::Region), Param(I::ParamTy), diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index e5bcbc67f946..93b6512acc50 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -1,6 +1,7 @@ use std::fmt; use std::hash::Hash; +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; @@ -12,15 +13,12 @@ use crate::visit::TypeVisitableExt as _; use crate::{self as ty, Interner}; /// `A: 'region` -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "A: Clone"), - Copy(bound = "A: Copy"), - Hash(bound = "A: Hash"), - PartialEq(bound = "A: PartialEq"), - Eq(bound = "A: Eq"), - Debug(bound = "A: fmt::Debug") -)] +#[derive_where(Clone; I: Interner, A: Clone)] +#[derive_where(Copy; I: Interner, A: Copy)] +#[derive_where(Hash; I: Interner, A: Hash)] +#[derive_where(PartialEq; I: Interner, A: PartialEq)] +#[derive_where(Eq; I: Interner, A: Eq)] +#[derive_where(Debug; I: Interner, A: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct OutlivesPredicate(pub A, pub I::Region); @@ -50,14 +48,7 @@ where /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the generic parameters. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct TraitRef { @@ -122,14 +113,7 @@ impl ty::Binder> { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct TraitPredicate { @@ -243,15 +227,7 @@ impl fmt::Display for PredicatePolarity { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum ExistentialPredicate { @@ -298,14 +274,7 @@ impl ty::Binder> { /// ``` /// The generic parameters don't include the erased `Self`, only trait /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct ExistentialTraitRef { @@ -351,14 +320,7 @@ impl ty::Binder> { } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct ExistentialProjection { @@ -454,15 +416,7 @@ impl AliasTermKind { /// * For a projection, this would be `>::N<...>`. /// * For an inherent projection, this would be `Ty::N<...>`. /// * For an opaque type, there is no explicit syntax. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct AliasTerm { @@ -491,7 +445,7 @@ pub struct AliasTerm { pub def_id: I::DefId, /// This field exists to prevent the creation of `AliasTerm` without using [`AliasTerm::new_from_args`]. - #[derivative(Debug = "ignore")] + #[derive_where(skip(Debug))] _use_alias_term_new_instead: (), } @@ -633,14 +587,7 @@ impl From> for AliasTerm { /// equality between arbitrary types. Processing an instance of /// Form #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct ProjectionPredicate { @@ -708,14 +655,7 @@ impl fmt::Debug for ProjectionPredicate { /// Used by the new solver. Unlike a `ProjectionPredicate` this can only be /// proven by actually normalizing `alias`. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct NormalizesTo { @@ -750,15 +690,7 @@ impl fmt::Debug for NormalizesTo { /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates /// whether the `a` type is the type that we should label as "expected" when /// presenting user diagnostics. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct SubtypePredicate { @@ -768,15 +700,7 @@ pub struct SubtypePredicate { } /// Encodes that we have to coerce *from* the `a` type to the `b` type. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct CoercePredicate { diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index b1d0f8d19b39..5b8b22244ba6 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; @@ -7,8 +8,7 @@ use crate::{self as ty, Interner}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] +#[derive_where(Clone, Copy, Hash, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ClauseKind { @@ -53,14 +53,7 @@ impl PartialEq for ClauseKind { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum PredicateKind { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 7abcc370c886..d56700f52eb8 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,3 +1,4 @@ +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -124,8 +125,7 @@ rustc_index::newtype_index! { /// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] +#[derive_where(Clone, Copy, Hash, Eq; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] pub enum RegionKind { /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`. diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 0439e7f857fe..745ee9d54d91 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -1,5 +1,6 @@ use std::iter; +use derive_where::derive_where; use rustc_ast_ir::Mutability; use tracing::{debug, instrument}; @@ -17,19 +18,11 @@ pub type RelateResult = Result>; /// a miscompilation or unsoundness. /// /// When in doubt, use `VarianceDiagInfo::default()` -#[derive(derivative::Derivative)] -#[derivative( - Copy(bound = ""), - Clone(bound = ""), - Debug(bound = ""), - Default(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Default; I: Interner)] pub enum VarianceDiagInfo { /// No additional information - this is the default. /// We will not add any additional information to error messages. - #[derivative(Default)] + #[derive_where(default)] None, /// We switched our variance because a generic argument occurs inside /// the invariant generic argument of another type. diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index 5ccda931f9c5..be4f1069cd16 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -1,10 +1,10 @@ +use derive_where::derive_where; use rustc_index::IndexVec; use super::{AvailableDepth, Cx, StackDepth, StackEntry}; use crate::data_structures::{HashMap, HashSet}; -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))] +#[derive_where(Debug, Clone, Copy; X: Cx)] struct QueryData { result: X::Result, proof_tree: X::ProofTree, @@ -20,8 +20,7 @@ struct Success { /// This contains results whose computation never hit the /// recursion limit in `success`, and all results which hit /// the recursion limit in `with_overflow`. -#[derive(derivative::Derivative)] -#[derivative(Default(bound = ""))] +#[derive_where(Default; X: Cx)] struct CacheEntry { success: Option>, /// We have to be careful when caching roots of cycles. @@ -32,8 +31,7 @@ struct CacheEntry { with_overflow: HashMap>>, } -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""))] +#[derive_where(Debug; X: Cx)] pub(super) struct CacheData<'a, X: Cx> { pub(super) result: X::Result, pub(super) proof_tree: X::ProofTree, @@ -41,11 +39,10 @@ pub(super) struct CacheData<'a, X: Cx> { pub(super) encountered_overflow: bool, // FIXME: This is currently unused, but impacts the design // by requiring a closure for `Cx::with_global_cache`. + #[allow(dead_code)] pub(super) nested_goals: &'a HashSet, } - -#[derive(derivative::Derivative)] -#[derivative(Default(bound = ""))] +#[derive_where(Default; X: Cx)] pub struct GlobalCache { map: HashMap>, } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index c2204becdfd7..4abf99b1ded8 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -3,6 +3,7 @@ use std::hash::Hash; use std::marker::PhantomData; use std::mem; +use derive_where::derive_where; use rustc_index::{Idx, IndexVec}; use tracing::debug; @@ -153,8 +154,7 @@ rustc_index::newtype_index! { pub struct StackDepth {} } -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""))] +#[derive_where(Debug; X: Cx)] struct StackEntry { input: X::Input, @@ -226,8 +226,7 @@ struct DetachedEntry { /// /// The provisional cache can theoretically result in changes to the observable behavior, /// see tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs. -#[derive(derivative::Derivative)] -#[derivative(Default(bound = ""))] +#[derive_where(Default; X: Cx)] struct ProvisionalCacheEntry { stack_depth: Option, with_inductive_stack: Option>, diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index 0733c730064b..e25df7a0f604 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -21,6 +21,7 @@ use crate::solve::{ CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; use crate::{Canonical, CanonicalVarValues, Interner}; +use derive_where::derive_where; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt::Debug; use std::hash::Hash; @@ -31,15 +32,12 @@ use std::hash::Hash; /// This is only ever used as [CanonicalState]. Any type information in proof /// trees used mechanically has to be canonicalized as we otherwise leak /// inference variables from a nested `InferCtxt`. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "T: Clone"), - Copy(bound = "T: Copy"), - PartialEq(bound = "T: PartialEq"), - Eq(bound = "T: Eq"), - Hash(bound = "T: Hash"), - Debug(bound = "T: Debug") -)] +#[derive_where(Clone; I: Interner, T: Clone)] +#[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(PartialEq; I: Interner, T: PartialEq)] +#[derive_where(Eq; I: Interner, T: Eq)] +#[derive_where(Hash; I: Interner, T: Hash)] +#[derive_where(Debug; I: Interner, T: Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct State { pub var_values: CanonicalVarValues, @@ -52,24 +50,21 @@ pub type CanonicalState = Canonical>; /// for the `CanonicalVarValues` of the canonicalized goal. /// We use this to map any [CanonicalState] from the local `InferCtxt` /// of the solver query to the `InferCtxt` of the caller. -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +#[derive_where(PartialEq, Eq, Hash; I: Interner)] pub struct GoalEvaluation { pub uncanonicalized_goal: Goal, pub orig_values: Vec, pub evaluation: CanonicalGoalEvaluation, } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub struct CanonicalGoalEvaluation { pub goal: CanonicalInput, pub kind: CanonicalGoalEvaluationKind, pub result: QueryResult, } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub enum CanonicalGoalEvaluationKind { Overflow, CycleInStack, @@ -77,8 +72,7 @@ pub enum CanonicalGoalEvaluationKind { Evaluation { final_revision: I::CanonicalGoalEvaluationStepRef }, } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub struct CanonicalGoalEvaluationStep { pub instantiated_goal: QueryInput, @@ -89,8 +83,7 @@ pub struct CanonicalGoalEvaluationStep { /// A self-contained computation during trait solving. This either /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation /// of a goal. -#[derive(derivative::Derivative)] -#[derivative(Debug(bound = ""), PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub struct Probe { /// What happened inside of this probe in chronological order. pub steps: Vec>, @@ -98,8 +91,7 @@ pub struct Probe { pub final_state: CanonicalState, } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub enum ProbeStep { /// We added a goal to the `EvalCtxt` which will get proven /// the next time `EvalCtxt::try_evaluate_added_goals` is called. @@ -121,15 +113,7 @@ pub enum ProbeStep { /// What kind of probe we're in. In case the probe represents a candidate, or /// the final result of the current goal - via [ProbeKind::Root] - we also /// store the [QueryResult]. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Hash(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub enum ProbeKind { /// The root inference context while proving a goal. diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 7934f996f0bd..7ac13755f5ff 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -3,6 +3,7 @@ pub mod inspect; use std::fmt; use std::hash::Hash; +use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; @@ -89,15 +90,12 @@ pub struct NoSolution; /// /// Most of the time the `param_env` contains the `where`-bounds of the function /// we're currently typechecking while the `predicate` is some trait bound. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "P: Clone"), - Copy(bound = "P: Copy"), - Hash(bound = "P: Hash"), - PartialEq(bound = "P: PartialEq"), - Eq(bound = "P: Eq"), - Debug(bound = "P: fmt::Debug") -)] +#[derive_where(Clone; I: Interner, P: Clone)] +#[derive_where(Copy; I: Interner, P: Copy)] +#[derive_where(Hash; I: Interner, P: Hash)] +#[derive_where(PartialEq; I: Interner, P: PartialEq)] +#[derive_where(Eq; I: Interner, P: Eq)] +#[derive_where(Debug; I: Interner, P: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct Goal { @@ -140,15 +138,12 @@ pub enum GoalSource { InstantiateHigherRanked, } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = "Goal: Clone"), - Copy(bound = "Goal: Copy"), - Hash(bound = "Goal: Hash"), - PartialEq(bound = "Goal: PartialEq"), - Eq(bound = "Goal: Eq"), - Debug(bound = "Goal: fmt::Debug") -)] +#[derive_where(Clone; I: Interner, Goal: Clone)] +#[derive_where(Copy; I: Interner, Goal: Copy)] +#[derive_where(Hash; I: Interner, Goal: Hash)] +#[derive_where(PartialEq; I: Interner, Goal: PartialEq)] +#[derive_where(Eq; I: Interner, Goal: Eq)] +#[derive_where(Debug; I: Interner, Goal: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct QueryInput { @@ -157,15 +152,7 @@ pub struct QueryInput { } /// Opaques that are defined in the inference context before a query is called. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = ""), - Default(bound = "") -)] +#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct PredefinedOpaquesData { @@ -173,15 +160,7 @@ pub struct PredefinedOpaquesData { } /// Possible ways the given goal can be proven. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] pub enum CandidateSource { /// A user written impl. /// @@ -265,15 +244,7 @@ pub enum BuiltinImplSource { TupleUnsizing, } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct Response { @@ -284,15 +255,7 @@ pub struct Response { } /// Additional constraints returned on success. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = ""), - Default(bound = "") -)] +#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct ExternalConstraintsData { @@ -301,15 +264,7 @@ pub struct ExternalConstraintsData { pub normalization_nested_goals: NestedNormalizationGoals, } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = ""), - Default(bound = "") -)] +#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct NestedNormalizationGoals(pub Vec<(GoalSource, Goal)>); @@ -386,8 +341,7 @@ impl MaybeCause { } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] +#[derive_where(PartialEq, Eq, Debug; I: Interner)] pub struct CacheData { pub result: QueryResult, pub proof_tree: Option, diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 4ffebef9f1f9..29993a50aeea 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,3 +1,5 @@ +use derive_where::derive_where; + #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -64,8 +66,7 @@ impl AliasTyKind { /// Types written by the user start out as `hir::TyKind` and get /// converted to this representation using `::lower_ty`. #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")] -#[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] +#[derive_where(Clone, Copy, Hash, Eq; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TyKind { /// The primitive boolean type. Written as `bool`. @@ -416,15 +417,7 @@ impl fmt::Debug for TyKind { /// * For a projection, this would be `>::N<...>`. /// * For an inherent projection, this would be `Ty::N<...>`. /// * For an opaque type, there is no explicit syntax. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct AliasTy { @@ -453,7 +446,7 @@ pub struct AliasTy { pub def_id: I::DefId, /// This field exists to prevent the creation of `AliasTy` without using [`AliasTy::new_from_args`]. - #[derivative(Debug = "ignore")] + #[derive_where(skip(Debug))] pub(crate) _use_alias_ty_new_instead: (), } @@ -944,15 +937,7 @@ impl fmt::Debug for InferTy { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Hash(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct TypeAndMut { @@ -960,14 +945,7 @@ pub struct TypeAndMut { pub mutbl: Mutability, } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Hash(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct FnSig { diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 24a7c0c67e90..36f02704de95 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -1,5 +1,6 @@ use std::ops::ControlFlow; +use derive_where::derive_where; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::{shift_region, TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -100,15 +101,7 @@ use crate::{self as ty, Interner}; /// * `GR`: The "return type", which is the type of value returned upon /// completion of the coroutine. /// * `GW`: The "coroutine witness". -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct ClosureArgs { /// Lifetime and type parameters from the enclosing function, @@ -210,15 +203,7 @@ impl ClosureArgs { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct CoroutineClosureArgs { pub args: I::GenericArgs, @@ -370,15 +355,7 @@ impl TypeVisitor for HasRegionsBoundAt { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { pub interior: I::Ty, @@ -552,15 +529,7 @@ impl TypeFolder for FoldEscapingRegions { } } -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct GenSig { pub resume_ty: I::Ty, @@ -569,15 +538,7 @@ pub struct GenSig { } /// Similar to `ClosureArgs`; see the above documentation for more. -#[derive(derivative::Derivative)] -#[derivative( - Clone(bound = ""), - Copy(bound = ""), - Hash(bound = ""), - PartialEq(bound = ""), - Eq(bound = ""), - Debug(bound = "") -)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct CoroutineArgs { pub args: I::GenericArgs, diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index 26834376e761..bdfcbed71e9a 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -31,7 +31,7 @@ error: rustc_dump_item_bounds LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..) })], def_id: DefId(..) }, Term::Ty(())), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, Term::Ty(())), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 4f15be4c7c88..9544bdbb468d 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,7 +1,7 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 329086ab7dfd..ccc7f30fa6fd 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,11 +1,11 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 2f1dfd19c483..7de30efae1cd 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,5 +1,5 @@ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 17da1f524796..d14b9d217da2 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -25,10 +25,10 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` --> $DIR/issue-118950-root-region.rs:19:1 | From 17c4e4a923d8a5db4a67bd42e18f8116eee78dfd Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 27 Jun 2024 14:56:27 +0300 Subject: [PATCH 15/49] derivative -> derive-where --- src/tools/tidy/src/deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c72fae0881e..0e51441bf3f5 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -254,7 +254,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "darling_macro", "datafrog", "deranged", - "derivative", + "derive-where", "derive_more", "derive_setters", "digest", From 59f88d3db92cddc209b15a4edf26216f5ec9daaa Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 10 Jul 2024 01:25:57 +0300 Subject: [PATCH 16/49] Silence clippy::derived_hash_with_manual_eq for now --- compiler/rustc_type_ir/src/canonical.rs | 3 +++ compiler/rustc_type_ir/src/const_kind.rs | 3 +++ compiler/rustc_type_ir/src/predicate_kind.rs | 3 +++ compiler/rustc_type_ir/src/region_kind.rs | 3 +++ compiler/rustc_type_ir/src/ty_kind.rs | 3 +++ 5 files changed, 15 insertions(+) diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 4e46a3a13aa5..f02ada152a44 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,3 +1,5 @@ +#![allow(clippy::derived_hash_with_manual_eq)] + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; @@ -167,6 +169,7 @@ pub enum CanonicalVarKind { PlaceholderConst(I::PlaceholderConst), } +// FIXME(GrigorenkoPV): consider not implementing PartialEq manually impl PartialEq for CanonicalVarKind { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index dab2d3bf695c..685bb5f9a8bf 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -1,3 +1,5 @@ +#![allow(clippy::derived_hash_with_manual_eq)] + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -43,6 +45,7 @@ pub enum ConstKind { Expr(I::ExprConst), } +// FIXME(GrigorenkoPV): consider not implementing PartialEq manually impl PartialEq for ConstKind { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 5b8b22244ba6..70b7c29bdfcc 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,3 +1,5 @@ +#![allow(clippy::derived_hash_with_manual_eq)] + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; @@ -38,6 +40,7 @@ pub enum ClauseKind { ConstEvaluatable(I::Const), } +// FIXME(GrigorenkoPV): consider not implementing PartialEq manually impl PartialEq for ClauseKind { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index d56700f52eb8..61ac83fcc98c 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,3 +1,5 @@ +#![allow(clippy::derived_hash_with_manual_eq)] + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -193,6 +195,7 @@ const fn regionkind_discriminant(value: &RegionKind) -> usize { } } +// FIXME(GrigorenkoPV): consider not implementing PartialEq manually // This is manually implemented because a derive would require `I: PartialEq` impl PartialEq for RegionKind { #[inline] diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 29993a50aeea..db883511d75a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,3 +1,5 @@ +#![allow(clippy::derived_hash_with_manual_eq)] + use derive_where::derive_where; #[cfg(feature = "nightly")] @@ -293,6 +295,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { } } +// FIXME(GrigorenkoPV): consider not implementing PartialEq manually // This is manually implemented because a derive would require `I: PartialEq` impl PartialEq for TyKind { #[inline] From 8edf9b808427dfbe4425b49d213351f907f58b40 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 20 Mar 2024 20:30:04 -0400 Subject: [PATCH 17/49] Item bounds can reference self projections and still be object safe --- .../src/traits/object_safety.rs | 120 ++++++++++++------ .../item-bounds-can-reference-self.rs | 11 ++ 2 files changed, 89 insertions(+), 42 deletions(-) create mode 100644 tests/ui/object-safety/item-bounds-can-reference-self.rs diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 1c6993bdd372..29c18512e6d9 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -12,16 +12,16 @@ use super::elaborate; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{self, Obligation, ObligationCause}; +use crate::traits::{Obligation, ObligationCause}; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; +use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{ self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; -use rustc_middle::ty::{GenericArg, GenericArgs}; use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -195,7 +195,13 @@ fn predicates_reference_self( .predicates .iter() .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp)) - .filter_map(|predicate| predicate_references_self(tcx, predicate)) + .filter_map(|(clause, sp)| { + // Super predicates cannot allow self projections, since they're + // impossible to make into existential bounds without eager resolution + // or something. + // e.g. `trait A: B`. + predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No) + }) .collect() } @@ -204,20 +210,25 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied()) - .filter_map(|c| predicate_references_self(tcx, c)) + .filter_map(|(clause, sp)| { + // Item bounds *can* have self projections, since they never get + // their self type erased. + predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes) + }) .collect() } fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, - (predicate, sp): (ty::Clause<'tcx>, Span), + trait_def_id: DefId, + predicate: ty::Clause<'tcx>, + sp: Span, + allow_self_projections: AllowSelfProjections, ) -> Option { - let self_ty = tcx.types.self_param; - let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into()); match predicate.kind().skip_binder() { ty::ClauseKind::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.trait_ref.args[1..].iter().any(has_self_ty).then_some(sp) + data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp) } ty::ClauseKind::Projection(ref data) => { // And similarly for projections. This should be redundant with @@ -235,9 +246,9 @@ fn predicate_references_self<'tcx>( // // This is ALT2 in issue #56288, see that for discussion of the // possible alternatives. - data.projection_term.args[1..].iter().any(has_self_ty).then_some(sp) + data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp) } - ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp), + ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp), ty::ClauseKind::WellFormed(..) | ty::ClauseKind::TypeOutlives(..) @@ -383,7 +394,12 @@ fn virtual_call_violations_for_method<'tcx>( let mut errors = Vec::new(); for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) { - if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) { + if contains_illegal_self_type_reference( + tcx, + trait_def_id, + sig.rebind(input_ty), + AllowSelfProjections::Yes, + ) { let span = if let Some(hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), .. @@ -396,7 +412,12 @@ fn virtual_call_violations_for_method<'tcx>( errors.push(MethodViolationCode::ReferencesSelfInput(span)); } } - if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) { + if contains_illegal_self_type_reference( + tcx, + trait_def_id, + sig.output(), + AllowSelfProjections::Yes, + ) { errors.push(MethodViolationCode::ReferencesSelfOutput); } if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) { @@ -482,7 +503,7 @@ fn virtual_call_violations_for_method<'tcx>( return false; } - contains_illegal_self_type_reference(tcx, trait_def_id, pred) + contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes) }) { errors.push(MethodViolationCode::WhereClauseReferencesSelf); } @@ -711,10 +732,17 @@ fn receiver_is_dispatchable<'tcx>( infcx.predicate_must_hold_modulo_regions(&obligation) } +#[derive(Copy, Clone)] +enum AllowSelfProjections { + Yes, + No, +} + fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, value: T, + allow_self_projections: AllowSelfProjections, ) -> bool { // This is somewhat subtle. In general, we want to forbid // references to `Self` in the argument and return types, @@ -759,6 +787,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, supertraits: Option>, + allow_self_projections: AllowSelfProjections, } impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { @@ -780,39 +809,41 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( ControlFlow::Continue(()) } ty::Alias(ty::Projection, ref data) => { - // This is a projected type `::X`. + match self.allow_self_projections { + AllowSelfProjections::Yes => { + // This is a projected type `::X`. - // Compute supertraits of current trait lazily. - if self.supertraits.is_none() { - let trait_ref = - ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)); - self.supertraits = Some( - traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(), - ); - } + // Compute supertraits of current trait lazily. + if self.supertraits.is_none() { + self.supertraits = + Some(self.tcx.supertrait_def_ids(self.trait_def_id).collect()); + } - // Determine whether the trait reference `Foo as - // SomeTrait` is in fact a supertrait of the - // current trait. In that case, this type is - // legal, because the type `X` will be specified - // in the object type. Note that we can just use - // direct equality here because all of these types - // are part of the formal parameter listing, and - // hence there should be no inference variables. - let is_supertrait_of_current_trait = self - .supertraits - .as_ref() - .unwrap() - .contains(&data.trait_ref(self.tcx).def_id); + // Determine whether the trait reference `Foo as + // SomeTrait` is in fact a supertrait of the + // current trait. In that case, this type is + // legal, because the type `X` will be specified + // in the object type. Note that we can just use + // direct equality here because all of these types + // are part of the formal parameter listing, and + // hence there should be no inference variables. + let is_supertrait_of_current_trait = self + .supertraits + .as_ref() + .unwrap() + .contains(&data.trait_ref(self.tcx).def_id); - // only walk contained types if it's not a super trait - if is_supertrait_of_current_trait { - ControlFlow::Continue(()) - } else { - t.super_visit_with(self) // POSSIBLY reporting an error + // only walk contained types if it's not a super trait + if is_supertrait_of_current_trait { + ControlFlow::Continue(()) + } else { + t.super_visit_with(self) // POSSIBLY reporting an error + } + } + AllowSelfProjections::No => t.super_visit_with(self), } } - _ => t.super_visit_with(self), // walk contained types, if any + _ => t.super_visit_with(self), } } @@ -824,7 +855,12 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( } value - .visit_with(&mut IllegalSelfTypeVisitor { tcx, trait_def_id, supertraits: None }) + .visit_with(&mut IllegalSelfTypeVisitor { + tcx, + trait_def_id, + supertraits: None, + allow_self_projections, + }) .is_break() } diff --git a/tests/ui/object-safety/item-bounds-can-reference-self.rs b/tests/ui/object-safety/item-bounds-can-reference-self.rs new file mode 100644 index 000000000000..4ae982e8f951 --- /dev/null +++ b/tests/ui/object-safety/item-bounds-can-reference-self.rs @@ -0,0 +1,11 @@ +//@ check-pass + +pub trait Foo { + type X: PartialEq; + type Y: PartialEq; + type Z: PartialEq; +} + +fn uwu(x: &dyn Foo) {} + +fn main() {} From 172cf9bef3411d479a0be98827647150cce48afd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Jun 2024 14:40:56 -0400 Subject: [PATCH 18/49] Fix unsoundness when associated types dont actually come from supertraits --- .../src/traits/object_safety.rs | 274 ++++++++++-------- .../almost-supertrait-associated-type.rs | 60 ++++ .../almost-supertrait-associated-type.stderr | 55 ++++ 3 files changed, 274 insertions(+), 115 deletions(-) create mode 100644 tests/ui/object-safety/almost-supertrait-associated-type.rs create mode 100644 tests/ui/object-safety/almost-supertrait-associated-type.stderr diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 29c18512e6d9..ec19cf276681 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -12,17 +12,16 @@ use super::elaborate; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{Obligation, ObligationCause}; +use crate::traits::{util, Obligation, ObligationCause}; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; -use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{ - self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitor, + self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt, + TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::abi::Abi; @@ -738,122 +737,50 @@ enum AllowSelfProjections { No, } +/// This is somewhat subtle. In general, we want to forbid +/// references to `Self` in the argument and return types, +/// since the value of `Self` is erased. However, there is one +/// exception: it is ok to reference `Self` in order to access +/// an associated type of the current trait, since we retain +/// the value of those associated types in the object type +/// itself. +/// +/// ```rust,ignore (example) +/// trait SuperTrait { +/// type X; +/// } +/// +/// trait Trait : SuperTrait { +/// type Y; +/// fn foo(&self, x: Self) // bad +/// fn foo(&self) -> Self // bad +/// fn foo(&self) -> Option // bad +/// fn foo(&self) -> Self::Y // OK, desugars to next example +/// fn foo(&self) -> ::Y // OK +/// fn foo(&self) -> Self::X // OK, desugars to next example +/// fn foo(&self) -> ::X // OK +/// } +/// ``` +/// +/// However, it is not as simple as allowing `Self` in a projected +/// type, because there are illegal ways to use `Self` as well: +/// +/// ```rust,ignore (example) +/// trait Trait : SuperTrait { +/// ... +/// fn foo(&self) -> ::X; +/// } +/// ``` +/// +/// Here we will not have the type of `X` recorded in the +/// object type, and we cannot resolve `Self as SomeOtherTrait` +/// without knowing what `Self` is. fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, value: T, allow_self_projections: AllowSelfProjections, ) -> bool { - // This is somewhat subtle. In general, we want to forbid - // references to `Self` in the argument and return types, - // since the value of `Self` is erased. However, there is one - // exception: it is ok to reference `Self` in order to access - // an associated type of the current trait, since we retain - // the value of those associated types in the object type - // itself. - // - // ```rust - // trait SuperTrait { - // type X; - // } - // - // trait Trait : SuperTrait { - // type Y; - // fn foo(&self, x: Self) // bad - // fn foo(&self) -> Self // bad - // fn foo(&self) -> Option // bad - // fn foo(&self) -> Self::Y // OK, desugars to next example - // fn foo(&self) -> ::Y // OK - // fn foo(&self) -> Self::X // OK, desugars to next example - // fn foo(&self) -> ::X // OK - // } - // ``` - // - // However, it is not as simple as allowing `Self` in a projected - // type, because there are illegal ways to use `Self` as well: - // - // ```rust - // trait Trait : SuperTrait { - // ... - // fn foo(&self) -> ::X; - // } - // ``` - // - // Here we will not have the type of `X` recorded in the - // object type, and we cannot resolve `Self as SomeOtherTrait` - // without knowing what `Self` is. - - struct IllegalSelfTypeVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - supertraits: Option>, - allow_self_projections: AllowSelfProjections, - } - - impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - match t.kind() { - ty::Param(_) => { - if t == self.tcx.types.self_param { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } - } - ty::Alias(ty::Projection, ref data) - if self.tcx.is_impl_trait_in_trait(data.def_id) => - { - // We'll deny these later in their own pass - ControlFlow::Continue(()) - } - ty::Alias(ty::Projection, ref data) => { - match self.allow_self_projections { - AllowSelfProjections::Yes => { - // This is a projected type `::X`. - - // Compute supertraits of current trait lazily. - if self.supertraits.is_none() { - self.supertraits = - Some(self.tcx.supertrait_def_ids(self.trait_def_id).collect()); - } - - // Determine whether the trait reference `Foo as - // SomeTrait` is in fact a supertrait of the - // current trait. In that case, this type is - // legal, because the type `X` will be specified - // in the object type. Note that we can just use - // direct equality here because all of these types - // are part of the formal parameter listing, and - // hence there should be no inference variables. - let is_supertrait_of_current_trait = self - .supertraits - .as_ref() - .unwrap() - .contains(&data.trait_ref(self.tcx).def_id); - - // only walk contained types if it's not a super trait - if is_supertrait_of_current_trait { - ControlFlow::Continue(()) - } else { - t.super_visit_with(self) // POSSIBLY reporting an error - } - } - AllowSelfProjections::No => t.super_visit_with(self), - } - } - _ => t.super_visit_with(self), - } - } - - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { - // Constants can only influence object safety if they are generic and reference `Self`. - // This is only possible for unevaluated constants, so we walk these here. - self.tcx.expand_abstract_consts(ct).super_visit_with(self) - } - } - value .visit_with(&mut IllegalSelfTypeVisitor { tcx, @@ -864,6 +791,123 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( .is_break() } +struct IllegalSelfTypeVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + supertraits: Option>>, + allow_self_projections: AllowSelfProjections, +} + +impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + match t.kind() { + ty::Param(_) => { + if t == self.tcx.types.self_param { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } + ty::Alias(ty::Projection, ref data) if self.tcx.is_impl_trait_in_trait(data.def_id) => { + // We'll deny these later in their own pass + ControlFlow::Continue(()) + } + ty::Alias(ty::Projection, ref data) => { + match self.allow_self_projections { + AllowSelfProjections::Yes => { + // This is a projected type `::X`. + + // Compute supertraits of current trait lazily. + if self.supertraits.is_none() { + self.supertraits = Some( + util::supertraits( + self.tcx, + ty::Binder::dummy(ty::TraitRef::identity( + self.tcx, + self.trait_def_id, + )), + ) + .map(|trait_ref| { + self.tcx.erase_regions( + self.tcx.instantiate_bound_regions_with_erased(trait_ref), + ) + }) + .collect(), + ); + } + + // Determine whether the trait reference `Foo as + // SomeTrait` is in fact a supertrait of the + // current trait. In that case, this type is + // legal, because the type `X` will be specified + // in the object type. Note that we can just use + // direct equality here because all of these types + // are part of the formal parameter listing, and + // hence there should be no inference variables. + let is_supertrait_of_current_trait = + self.supertraits.as_ref().unwrap().contains( + &data.trait_ref(self.tcx).fold_with( + &mut EraseEscapingBoundRegions { + tcx: self.tcx, + binder: ty::INNERMOST, + }, + ), + ); + + // only walk contained types if it's not a super trait + if is_supertrait_of_current_trait { + ControlFlow::Continue(()) + } else { + t.super_visit_with(self) // POSSIBLY reporting an error + } + } + AllowSelfProjections::No => t.super_visit_with(self), + } + } + _ => t.super_visit_with(self), + } + } + + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { + // Constants can only influence object safety if they are generic and reference `Self`. + // This is only possible for unevaluated constants, so we walk these here. + self.tcx.expand_abstract_consts(ct).super_visit_with(self) + } +} + +struct EraseEscapingBoundRegions<'tcx> { + tcx: TyCtxt<'tcx>, + binder: ty::DebruijnIndex, +} + +impl<'tcx> TypeFolder> for EraseEscapingBoundRegions<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + where + T: TypeFoldable>, + { + self.binder.shift_in(1); + let result = t.super_fold_with(self); + self.binder.shift_out(1); + result + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReBound(debruijn, _) = *r + && debruijn < self.binder + { + r + } else { + self.tcx.lifetimes.re_erased + } + } +} + pub fn contains_illegal_impl_trait_in_trait<'tcx>( tcx: TyCtxt<'tcx>, fn_def_id: DefId, diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.rs b/tests/ui/object-safety/almost-supertrait-associated-type.rs new file mode 100644 index 000000000000..963cdff526ee --- /dev/null +++ b/tests/ui/object-safety/almost-supertrait-associated-type.rs @@ -0,0 +1,60 @@ +// Test for fixed unsoundness in #126079. +// Enforces that the associated types that are object safe + +use std::marker::PhantomData; + +fn transmute(t: T) -> U { + (&PhantomData:: as &dyn Foo).transmute(t) + //~^ ERROR the trait `Foo` cannot be made into an object + //~| ERROR the trait `Foo` cannot be made into an object +} + +struct ActuallySuper; +struct NotActuallySuper; +trait Super { + type Assoc; +} + +trait Dyn { + type Out; +} +impl Dyn for dyn Foo + '_ { +//~^ ERROR the trait `Foo` cannot be made into an object + type Out = U; +} +impl + ?Sized, U> Super for S { + type Assoc = U; +} + +trait Foo: Super +where + ::Assoc: Super +{ + fn transmute(&self, t: T) -> >::Assoc; +} + +trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} + +impl Foo for PhantomData { + fn transmute(&self, t: T) -> T { + t + } +} +impl Super for PhantomData { + type Assoc = T; +} +impl Super for PhantomData { + type Assoc = T; +} + +fn main() { + let x = String::from("hello, world"); + let s = transmute::<&str, &'static str>(x.as_str()); + drop(x); + println!("> {s}"); +} diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.stderr b/tests/ui/object-safety/almost-supertrait-associated-type.stderr new file mode 100644 index 000000000000..97a51c2f3816 --- /dev/null +++ b/tests/ui/object-safety/almost-supertrait-associated-type.stderr @@ -0,0 +1,55 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/almost-supertrait-associated-type.rs:21:20 + | +LL | impl Dyn for dyn Foo + '_ { + | ^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/almost-supertrait-associated-type.rs:33:34 + | +LL | trait Foo: Super + | --- this trait cannot be made into an object... +... +LL | fn transmute(&self, t: T) -> >::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type + = help: consider moving `transmute` to another trait + = help: only type `std::marker::PhantomData` implements the trait, consider using it directly instead + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/almost-supertrait-associated-type.rs:7:27 + | +LL | (&PhantomData:: as &dyn Foo).transmute(t) + | ^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/almost-supertrait-associated-type.rs:33:34 + | +LL | trait Foo: Super + | --- this trait cannot be made into an object... +... +LL | fn transmute(&self, t: T) -> >::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type + = help: consider moving `transmute` to another trait + = help: only type `std::marker::PhantomData` implements the trait, consider using it directly instead + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/almost-supertrait-associated-type.rs:7:6 + | +LL | (&PhantomData:: as &dyn Foo).transmute(t) + | ^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/almost-supertrait-associated-type.rs:33:34 + | +LL | trait Foo: Super + | --- this trait cannot be made into an object... +... +LL | fn transmute(&self, t: T) -> >::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type + = help: consider moving `transmute` to another trait + = help: only type `std::marker::PhantomData` implements the trait, consider using it directly instead + = note: required for the cast from `&PhantomData` to `&dyn Foo` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. From 89f273f40dafb693139496ed6f914872b6533fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 9 Jul 2024 16:46:09 +0000 Subject: [PATCH 19/49] Replace ASCII control chars with Unicode Control Pictures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` error: bare CR not allowed in doc-comment --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32 | LL | /// doc comment with bare CR: '␍' | ^ ``` --- compiler/rustc_errors/src/emitter.rs | 69 ++++++++++++++---- ...-bare-cr-string-literal-doc-comment.stderr | 14 ++-- tests/ui/parser/bad-char-literals.rs | Bin 496 -> 608 bytes tests/ui/parser/bad-char-literals.stderr | 17 ++++- tests/ui/parser/issues/issue-66473.stderr | Bin 1061 -> 1209 bytes tests/ui/parser/issues/issue-68629.stderr | Bin 944 -> 976 bytes tests/ui/parser/issues/issue-68730.stderr | Bin 1266 -> 1294 bytes .../raw/raw-byte-string-literals.stderr | 2 +- ...ral-carriage-returns-in-doc-comment.stderr | 6 +- .../trailing-carriage-return-in-string.stderr | 2 +- tests/ui/parser/utf16-be-without-bom.stderr | Bin 3641 -> 4029 bytes tests/ui/parser/utf16-le-without-bom.stderr | Bin 3603 -> 3939 bytes .../rfc-3348-c-string-literals/no-nuls.stderr | Bin 2028 -> 2040 bytes tests/ui/str/str-escape.stderr | 2 +- 14 files changed, 81 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index aa47ca166764..95e1b5348b73 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -677,10 +677,7 @@ impl HumanEmitter { .skip(left) .take_while(|ch| { // Make sure that the trimming on the right will fall within the terminal width. - // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` - // is. For now, just accept that sometimes the code line will be longer than - // desired. - let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + let next = char_width(*ch); if taken + next > right - left { return false; } @@ -742,11 +739,7 @@ impl HumanEmitter { let left = margin.left(source_string.len()); // Account for unicode characters of width !=0 that were removed. - let left = source_string - .chars() - .take(left) - .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) - .sum(); + let left = source_string.chars().take(left).map(|ch| char_width(ch)).sum(); self.draw_line( buffer, @@ -2039,7 +2032,7 @@ impl HumanEmitter { let sub_len: usize = if is_whitespace_addition { &part.snippet } else { part.snippet.trim() } .chars() - .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .map(|ch| char_width(ch)) .sum(); let offset: isize = offsets @@ -2076,11 +2069,8 @@ impl HumanEmitter { } // length of the code after substitution - let full_sub_len = part - .snippet - .chars() - .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) - .sum::() as isize; + let full_sub_len = + part.snippet.chars().map(|ch| char_width(ch)).sum::() as isize; // length of the code to be substituted let snippet_len = span_end_pos as isize - span_start_pos as isize; @@ -2580,6 +2570,40 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2068}', ""), ('\u{202C}', ""), ('\u{2069}', ""), + // In terminals without Unicode support the following will be garbled, but in *all* terminals + // the underlying codepoint will be as well. We could gate this replacement behind a "unicode + // support" gate. + ('\u{0000}', "␀"), + ('\u{0001}', "␁"), + ('\u{0002}', "␂"), + ('\u{0003}', "␃"), + ('\u{0004}', "␄"), + ('\u{0005}', "␅"), + ('\u{0006}', "␆"), + ('\u{0007}', "␇"), + ('\u{0008}', "␈"), + ('\u{000B}', "␋"), + ('\u{000C}', "␌"), + ('\u{000D}', "␍"), + ('\u{000E}', "␎"), + ('\u{000F}', "␏"), + ('\u{0010}', "␐"), + ('\u{0011}', "␑"), + ('\u{0012}', "␒"), + ('\u{0013}', "␓"), + ('\u{0014}', "␔"), + ('\u{0015}', "␕"), + ('\u{0016}', "␖"), + ('\u{0017}', "␗"), + ('\u{0018}', "␘"), + ('\u{0019}', "␙"), + ('\u{001A}', "␚"), + ('\u{001B}', "␛"), + ('\u{001C}', "␜"), + ('\u{001D}', "␝"), + ('\u{001E}', "␞"), + ('\u{001F}', "␟"), + ('\u{007F}', "␡"), ]; fn normalize_whitespace(str: &str) -> String { @@ -2590,6 +2614,21 @@ fn normalize_whitespace(str: &str) -> String { s } +fn char_width(ch: char) -> usize { + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now, + // just accept that sometimes the code line will be longer than desired. + match ch { + '\t' => 4, + '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}' + | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}' + | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}' + | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}' + | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}' + | '\u{007F}' => 1, + _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1), + } +} + fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { buffer.puts(line, col, "| ", Style::LineNumber); } diff --git a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr index da80991c727f..841d5236edef 100644 --- a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr +++ b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr @@ -1,31 +1,31 @@ error: bare CR not allowed in doc-comment --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32 | -LL | /// doc comment with bare CR: ' ' +LL | /// doc comment with bare CR: '␍' | ^ error: bare CR not allowed in block doc-comment --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:7:38 | -LL | /** block doc comment with bare CR: ' ' */ +LL | /** block doc comment with bare CR: '␍' */ | ^ error: bare CR not allowed in doc-comment --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:12:36 | -LL | //! doc comment with bare CR: ' ' +LL | //! doc comment with bare CR: '␍' | ^ error: bare CR not allowed in block doc-comment --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:15:42 | -LL | /*! block doc comment with bare CR: ' ' */ +LL | /*! block doc comment with bare CR: '␍' */ | ^ error: bare CR not allowed in string, use `\r` instead --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18 | -LL | let _s = "foo bar"; +LL | let _s = "foo␍bar"; | ^ | help: escape the character @@ -36,13 +36,13 @@ LL | let _s = "foo\rbar"; error: bare CR not allowed in raw string --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19 | -LL | let _s = r"bar foo"; +LL | let _s = r"bar␍foo"; | ^ error: unknown character escape: `\r` --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19 | -LL | let _s = "foo\ bar"; +LL | let _s = "foo\␍bar"; | ^ unknown character escape | = help: this is an isolated carriage return; consider checking your editor and version control settings diff --git a/tests/ui/parser/bad-char-literals.rs b/tests/ui/parser/bad-char-literals.rs index 748b4a22253f52301df92a22cf2b848ac6e4726f..c3d55d3f7e3bfbb53c98f8ce78ebfe4bff3fe477 100644 GIT binary patch delta 72 zcmeys{D5V{Oh#V6P#+&I1qB5KbzKJC$##qqYB`xDsYQu73b~1u3i)|Cl?uuEc_oRN cc?$V?sS3&YDX9hdnRz9XIT=+a&twb-05OplQ~&?~ delta 11 ScmaFB@_~87OvcHaOyK|>hy)h^ diff --git a/tests/ui/parser/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr index 89253d7d4aac..38889da5da12 100644 --- a/tests/ui/parser/bad-char-literals.stderr +++ b/tests/ui/parser/bad-char-literals.stderr @@ -25,7 +25,7 @@ LL | '\n'; error: character constant must be escaped: `\r` --> $DIR/bad-char-literals.rs:15:6 | -LL | ' '; +LL | '␍'; | ^ | help: escape the character @@ -33,8 +33,19 @@ help: escape the character LL | '\r'; | ++ +error: character literal may only contain one codepoint + --> $DIR/bad-char-literals.rs:18:5 + | +LL | '-␀-'; + | ^^^^ + | +help: if you meant to write a string literal, use double quotes + | +LL | "-␀-"; + | ~ ~ + error: character constant must be escaped: `\t` - --> $DIR/bad-char-literals.rs:18:6 + --> $DIR/bad-char-literals.rs:21:6 | LL | ' '; | ^^^^ @@ -44,5 +55,5 @@ help: escape the character LL | '\t'; | ++ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index 0e8b0a5da220569b607fe3512ae59ee94e3fcf1b..4be992d58460ebac5cf5fa9ee562da839f670d59 100644 GIT binary patch delta 316 zcmZ3=v6FK`kjB=(S*5Xk0#88 z7&7@bW4IW)AhK<;a;8?MU;!>4AB7qPbhQ&Nte9-eoNNa%j#LtCu!4f_WItwUG3*vh Ie#qdTN7XWa45$gZ| diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr index 2562baa1c49c3034012d9721c128aecc4303dc02..ccb0624208b2e20aee028a8efb2fd0fc25d61c94 100644 GIT binary patch delta 125 zcmdnMet~_0pV*@ba~@5YUsC*NLW5#-btadBfzJYy$AFGUfNioC3{rVF-bYSc#2xGDe<2@z@hRF@gqMK!zSQ(+By3D>1(EtFB CauJFE diff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr index 5bca5bbebeacb44984c8679e4d2c4757be4ee742..6025ea8c1ae7fbdec8c78ea332e3560ee2796981 100644 GIT binary patch delta 96 zcmeyw*~c{@kmJ#WhSc0g6B;IlK7q3*+cLgDa5R~AAvn*O(h!_L=E(@o3+7$~r;?=- E00Eybk^lez delta 67 zcmeC<`ouXQkcA;NmtkV$6EHp5mGK3HVal`%!uZaV24SQ!PX;q4vGjuJ$x~S>0kO^# AssI20 diff --git a/tests/ui/parser/raw/raw-byte-string-literals.stderr b/tests/ui/parser/raw/raw-byte-string-literals.stderr index a2f27d1ed70a..a20ce845c326 100644 --- a/tests/ui/parser/raw/raw-byte-string-literals.stderr +++ b/tests/ui/parser/raw/raw-byte-string-literals.stderr @@ -1,7 +1,7 @@ error: bare CR not allowed in raw string --> $DIR/raw-byte-string-literals.rs:4:9 | -LL | br"a "; +LL | br"a␍"; | ^ error: non-ASCII character in raw byte string literal diff --git a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr index 07066fc22e6c..3150570e1c90 100644 --- a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr +++ b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr @@ -1,19 +1,19 @@ error: bare CR not allowed in doc-comment --> $DIR/several-carriage-returns-in-doc-comment.rs:6:12 | -LL | /// This do c comment contains three isolated `\r` symbols +LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols | ^ error: bare CR not allowed in doc-comment --> $DIR/several-carriage-returns-in-doc-comment.rs:6:32 | -LL | /// This do c comment contains three isolated `\r` symbols +LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols | ^ error: bare CR not allowed in doc-comment --> $DIR/several-carriage-returns-in-doc-comment.rs:6:52 | -LL | /// This do c comment contains three isolated `\r` symbols +LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols | ^ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/trailing-carriage-return-in-string.stderr b/tests/ui/parser/trailing-carriage-return-in-string.stderr index fa2677921b32..c5949432af89 100644 --- a/tests/ui/parser/trailing-carriage-return-in-string.stderr +++ b/tests/ui/parser/trailing-carriage-return-in-string.stderr @@ -1,7 +1,7 @@ error: unknown character escape: `\r` --> $DIR/trailing-carriage-return-in-string.rs:10:25 | -LL | let bad = "This is \ a test"; +LL | let bad = "This is \␍ a test"; | ^ unknown character escape | = help: this is an isolated carriage return; consider checking your editor and version control settings diff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr index c041f3ecf53b22d8bfd994f7a8c24d583594e027..28cf6d97e96c2a8d08d193f97d4289da04c2aa38 100644 GIT binary patch literal 4029 zcmYc-D#|aiQYg*K&dV>)Qz$M;EGkjRPg5w#&rZ#=Qiv(7HmK!NP|(%2Q&4g74AL(x zNi#IlO-j`*&n(HvFD=nc%Fop+Dz-AQGUQTFP^jVZ@lmKzcr>9Q?a_pWyhjrnK)2C#00I4}hwY!xz6a|)~!it|g0l2aAZGILUk z6>>|9OB9mx^GXsk^Atiu+;lAzQuC7YQ&LkDN>VFIbQDVSQY#8llS@)l6!J=Qaukv( zOF-H((=$pG@{^NGixkQ;Qu7oN6;d+O(o&03^GYBFWagzSWELxw7N@3gaZxW!j6pu3 zG)#tDpqNr6P=;Hmm{TWIhFh>$QYl!5TeuifrMOi9fniqW8d9gw1%=G8OEgp}dWU7$ zP^$nQmVraHVt6=)juG|B;$ay)R4kB(W%y9DR33Bz1n-aK=cR%=mI;ap3i(9}3077K zItpp|rFkg|33&;`bumq-(in_Wz~d%}4Un#9a(-TMW=d+2LQ!gNei^8XSdx*dP+X9h zoT^ZguTWf&nv!b*TFk`-07RqE{Qv*} literal 3641 zcmYc-D#|aiQYg*K&dV>)Qz$M;EGkjRPg5w#&rZ#=Qiv(7HmK!NP|(%2Q&4g74AL(x zNi#IlO-j`*&n(HvFD=nc%Fop+Dz-AQGUQTFP^jVZ@lmKzU`S)gV^CnoWk_VmWXNOC zV9;bxV5nxOWdN&Dhyzm~!d4+8HK)Kzp*X*^C^=OjEi)&zSRuExxI`g2Kd&S)GfyEj z#7);iAvG^KKP5Fqp(M4UL`R`CFSVi|HMt};MIo;=Cr2TvvIL|pGd-h3AwM~}v`C>m zBQ;MUQ6VKWEiJVuHLnC>KxSULLT0f-X>n=_7Z>$>ZVd7XaXuezUN%-0O=A`(2 zxOv`^B+m~w-y4!p*eQU(Fe~v4Nh$I`{vUP;fTV(NScU*;#ow?D0ul?s;TQ%+q?Uxk zG7v~E4u@qZkX|MZx?q6!EAsPFLEWGP#RP@?B83Dis{|c|wEWV%6orJm1mZeGCL}bG z;uP@M3^51NQA*CwE6z+wEm9~-&CM?Zb!bX5QWc5|5|dLEO7azo3sQ4(6tYt*%kzs; x6cWfn8%#H9S95|G&`rC?JHO%w`>Qp+;)ON$l2-KJtLE&w*9SBd}t diff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr index cc2220441ac1073c755b178c4da74085faedd2a1..53004ac942d988ea867e0ea7573b4ffd6cfbd026 100644 GIT binary patch literal 3939 zcmYc-D#|aiQYg*K&dV>)Qz$M;EGkjRPg5w#&rZ#=Qiv(7HmK!NP|(%2Q&4g74AL(x zNi#Il%}LcQ&n(HvFD=nc%Fop+Dz-AQGU8HDP^jVZ@lmKzNP9G)A@9+I28Blx8gd^^ zXh?iCp&=70rtxS(gC&TF%&nrpH%u@&ranrR>NX<*mPf1NtC`qj-(NQSPORXqKO)g1IQOGOJ$x%qE zECFfDOwTA$$WKl#EmA1YNX=77R7lB8OG_ZaQ$-B#J>}=6f;xc-iU|t& zMG6U4RtY)^Y5ApjDGCXB3B+{=jgdS{Zg)@tkAon_LwbqH`FX{eDXB#YMX9;@WuV?% zNk*zdaY15oszOP=LUBQAPL4u$YGrwTQHnxB8rTc)t}5yM)Vex&FEKGGzo-OcVM;03 XDnk>6f}+&2%>2?~1#m~Qn2QSlk2ad; literal 3603 zcmYc-D#|aiQYg*K&dV>)Qz$M;EGkjRPg5w#&rZ#=Qiv(7HmK!NP|(%2Q&4g74AL(x zNi#Il%}LcQ&n(HvFD=nc%Fop+Dz-AQGU8HDP^jVZ@lmKzNMp!jP+-VqNMy)l$Yao8 z&}2|xsAi~T04q^Yhy&9g!d4+8HK)Kzp*X*^C^=OjEi)&zSRuExxI`g2Kd&S)GfyEj z#7);iAvG^KKP5Fqp(M4UL`R`CFSVi|HMt};MIo;=Cr2TvvIL|pGd-h3AwM~}v`C>m zBQ;MUQ6VKWEiJVuHLnC>KxSULLT0f-X>n=_7Z>$>ZUXWNaXuezUN%-0O7Nq!n zxOv{tfF$1!JMWWF+9`m*Fe~y5Nh$L{{vUP;fTWUdScU*;<==1&0wWR&!C@H&q?Uxk zG7v~E4u@YTm|7VkH3^_i{lQf2!TSvPd8wc-PJ&{BLVl4#f|XT*jzU^~Xu=T7!FxN2N%=)3Afr=C!G;=|C=?W>mSyIb7At@|M8#ZO E0L>Is2mk;8 diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr index a05dea3ff07e6003bbb459d776ea0b24a2338983..13cbd8370db64de67fd796516a2f95ff7df8f217 100644 GIT binary patch delta 66 zcmaFE|AT)+HY4++2@R8T82^Ci&6!NKFoD#`J}lEgf|E0u(l&ds+JhxFcd^NU8IzZ@ Gy8-~P(Hh_Y delta 62 zcmeyt|Av1j4q~+j2^O-7Z(hyD3So*( IKFO{R09Bt6mjD0& diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr index c4aee2a110a5..599c8de97578 100644 --- a/tests/ui/str/str-escape.stderr +++ b/tests/ui/str/str-escape.stderr @@ -22,7 +22,7 @@ warning: whitespace symbol '\u{c}' is not skipped | LL | let s = b"a\ | ________________^ -LL | | b"; +LL | | ␌b"; | | ^- whitespace symbol '\u{c}' is not skipped | |____| | From 2d7795dfb942d49d447837ef43db89216de15696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 9 Jul 2024 17:00:19 +0000 Subject: [PATCH 20/49] Be more accurate about calculating `display_col` from a `BytePos` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No longer track "zero-width" chars in `SourceMap`, read directly from the line when calculating the `display_col` of a `BytePos`. Move `char_width` to `rustc_span` and use it from the emitter. This change allows the following to properly align in terminals (depending on the font, the replaced control codepoints are rendered as 1 or 2 width, on my terminal they are rendered as 1, on VSCode text they are rendered as 2): ``` error: this file contains an unclosed delimiter --> $DIR/issue-68629.rs:5:17 | LL | ␜␟ts␀![{i | -- unclosed delimiter | | | unclosed delimiter LL | ␀␀ fn rݻoa>rݻm | ^ ``` --- Cargo.lock | 1 - compiler/rustc_errors/Cargo.toml | 1 - compiler/rustc_errors/src/emitter.rs | 17 +-- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 - .../src/ich/impls_syntax.rs | 6 - .../rustc_span/src/analyze_source_file.rs | 40 +----- .../src/analyze_source_file/tests.rs | 24 +--- compiler/rustc_span/src/lib.rs | 133 +++++------------- compiler/rustc_span/src/source_map.rs | 2 - compiler/rustc_span/src/source_map/tests.rs | 2 - .../doctest/test-compile-fail3.stderr | 2 +- tests/ui/codemap_tests/tab_2.stderr | 2 +- tests/ui/error-codes/E0601.stderr | 2 +- tests/ui/issues/issue-44078.stderr | 2 +- tests/ui/lexer/unterminated-comment.stderr | 2 +- .../lexer/unterminated-nested-comment.stderr | 2 +- tests/ui/lint/issue-104897.stderr | 2 +- ...07423-unused-delim-only-one-no-pair.stderr | 2 +- tests/ui/parser/bad-char-literals.stderr | 4 +- tests/ui/parser/brace-in-let-chain.stderr | 2 +- tests/ui/parser/byte-string-literals.stderr | 2 +- tests/ui/parser/deli-ident-issue-1.stderr | 2 +- tests/ui/parser/issues/issue-103451.stderr | 2 +- tests/ui/parser/issues/issue-104367.stderr | 2 +- tests/ui/parser/issues/issue-105209.stderr | 2 +- tests/ui/parser/issues/issue-107705.stderr | 2 +- tests/ui/parser/issues/issue-2354.stderr | 2 +- tests/ui/parser/issues/issue-62546.stderr | 2 +- tests/ui/parser/issues/issue-62554.stderr | 2 +- tests/ui/parser/issues/issue-62881.stderr | 2 +- tests/ui/parser/issues/issue-62894.stderr | 2 +- tests/ui/parser/issues/issue-62973.stderr | 2 +- tests/ui/parser/issues/issue-63116.stderr | 2 +- tests/ui/parser/issues/issue-63135.stderr | 2 +- tests/ui/parser/issues/issue-66473.stderr | 10 +- ...invalid-syntax-in-enum-discriminant.stderr | 2 +- tests/ui/parser/issues/issue-68629.stderr | 14 +- tests/ui/parser/issues/issue-68730.stderr | 12 +- tests/ui/parser/issues/issue-81804.stderr | 2 +- tests/ui/parser/issues/issue-81827.stderr | 2 +- tests/ui/parser/issues/issue-84104.stderr | 2 +- tests/ui/parser/issues/issue-84148-2.stderr | 2 +- tests/ui/parser/issues/issue-88770.stderr | 2 +- .../missing-close-brace-in-impl-trait.stderr | 2 +- .../missing-close-brace-in-struct.stderr | 2 +- .../missing-close-brace-in-trait.stderr | 2 +- .../parser-ice-ed2021-await-105210.stderr | 2 +- tests/ui/parser/parser-recovery-1.stderr | 2 +- ...ral-carriage-returns-in-doc-comment.stderr | 4 +- tests/ui/parser/unbalanced-doublequote.stderr | 2 +- tests/ui/parser/unclosed-braces.stderr | 2 +- .../unmatched-delimiter-at-end-of-file.stderr | 2 +- tests/ui/parser/use-unclosed-brace.stderr | 2 +- tests/ui/parser/utf16-be-without-bom.stderr | 28 ++-- tests/ui/parser/utf16-le-without-bom.stderr | 24 ++-- .../rustdoc/unterminated-doc-comment.stderr | 2 +- ...incompatible-closure-captures-93117.stderr | 2 +- tests/ui/str/str-escape.stderr | 4 +- tests/ui/suggestions/issue-94171.stderr | 2 +- tests/ui/typeck/issue-91334.stderr | 2 +- 60 files changed, 134 insertions(+), 278 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c1607e4c1ac..d6060992ef21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4008,7 +4008,6 @@ dependencies = [ "termcolor", "termize", "tracing", - "unicode-width", "windows", ] diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index cc114fdcd8c3..2fff9f2de50f 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -26,7 +26,6 @@ serde_json = "1.0.59" termcolor = "1.2.0" termize = "0.1.1" tracing = "0.1" -unicode-width = "0.1.4" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 95e1b5348b73..16fa0ff7a2d6 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -8,7 +8,7 @@ //! The output types are defined in `rustc_session::config::ErrorOutputType`. use rustc_span::source_map::SourceMap; -use rustc_span::{FileLines, FileName, SourceFile, Span}; +use rustc_span::{char_width, FileLines, FileName, SourceFile, Span}; use crate::snippet::{ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, @@ -2614,21 +2614,6 @@ fn normalize_whitespace(str: &str) -> String { s } -fn char_width(ch: char) -> usize { - // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now, - // just accept that sometimes the code line will be longer than desired. - match ch { - '\t' => 4, - '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}' - | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}' - | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}' - | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}' - | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}' - | '\u{007F}' => 1, - _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1), - } -} - fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { buffer.puts(line, col, "| ", Style::LineNumber); } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0ba9b940eed1..9f2fe2547538 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1727,7 +1727,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { source_len, lines, multibyte_chars, - non_narrow_chars, normalized_pos, stable_id, .. @@ -1779,7 +1778,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.cnum, lines, multibyte_chars, - non_narrow_chars, normalized_pos, source_file_index, ); diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index 5bd4fe04848f..39da5e395c42 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -73,7 +73,6 @@ impl<'a> HashStable> for SourceFile { source_len: _, lines: _, ref multibyte_chars, - ref non_narrow_chars, ref normalized_pos, } = *self; @@ -98,11 +97,6 @@ impl<'a> HashStable> for SourceFile { char_pos.hash_stable(hcx, hasher); } - non_narrow_chars.len().hash_stable(hcx, hasher); - for &char_pos in non_narrow_chars.iter() { - char_pos.hash_stable(hcx, hasher); - } - normalized_pos.len().hash_stable(hcx, hasher); for &char_pos in normalized_pos.iter() { char_pos.hash_stable(hcx, hasher); diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index d9e1ebaf0bce..ba7e0cec5bd8 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -1,5 +1,4 @@ use super::*; -use unicode_width::UnicodeWidthChar; #[cfg(test)] mod tests; @@ -9,15 +8,12 @@ mod tests; /// /// This function will use an SSE2 enhanced implementation if hardware support /// is detected at runtime. -pub fn analyze_source_file( - src: &str, -) -> (Vec, Vec, Vec) { +pub fn analyze_source_file(src: &str) -> (Vec, Vec) { let mut lines = vec![RelativeBytePos::from_u32(0)]; let mut multi_byte_chars = vec![]; - let mut non_narrow_chars = vec![]; // Calls the right implementation, depending on hardware support available. - analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars, &mut non_narrow_chars); + analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars); // The code above optimistically registers a new line *after* each \n // it encounters. If that point is already outside the source_file, remove @@ -30,7 +26,7 @@ pub fn analyze_source_file( } } - (lines, multi_byte_chars, non_narrow_chars) + (lines, multi_byte_chars) } cfg_match! { @@ -39,11 +35,10 @@ cfg_match! { src: &str, lines: &mut Vec, multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec, ) { if is_x86_feature_detected!("sse2") { unsafe { - analyze_source_file_sse2(src, lines, multi_byte_chars, non_narrow_chars); + analyze_source_file_sse2(src, lines, multi_byte_chars); } } else { analyze_source_file_generic( @@ -52,7 +47,6 @@ cfg_match! { RelativeBytePos::from_u32(0), lines, multi_byte_chars, - non_narrow_chars, ); } } @@ -66,7 +60,6 @@ cfg_match! { src: &str, lines: &mut Vec, multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec, ) { #[cfg(target_arch = "x86")] use std::arch::x86::*; @@ -159,7 +152,6 @@ cfg_match! { RelativeBytePos::from_usize(scan_start), lines, multi_byte_chars, - non_narrow_chars, ); } @@ -172,7 +164,6 @@ cfg_match! { RelativeBytePos::from_usize(tail_start), lines, multi_byte_chars, - non_narrow_chars, ); } } @@ -183,7 +174,6 @@ cfg_match! { src: &str, lines: &mut Vec, multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec, ) { analyze_source_file_generic( src, @@ -191,7 +181,6 @@ cfg_match! { RelativeBytePos::from_u32(0), lines, multi_byte_chars, - non_narrow_chars, ); } } @@ -205,7 +194,6 @@ fn analyze_source_file_generic( output_offset: RelativeBytePos, lines: &mut Vec, multi_byte_chars: &mut Vec, - non_narrow_chars: &mut Vec, ) -> usize { assert!(src.len() >= scan_len); let mut i = 0; @@ -227,16 +215,8 @@ fn analyze_source_file_generic( let pos = RelativeBytePos::from_usize(i) + output_offset; - match byte { - b'\n' => { - lines.push(pos + RelativeBytePos(1)); - } - b'\t' => { - non_narrow_chars.push(NonNarrowChar::Tab(pos)); - } - _ => { - non_narrow_chars.push(NonNarrowChar::ZeroWidth(pos)); - } + if let b'\n' = byte { + lines.push(pos + RelativeBytePos(1)); } } else if byte >= 127 { // The slow path: @@ -252,14 +232,6 @@ fn analyze_source_file_generic( let mbc = MultiByteChar { pos, bytes: char_len as u8 }; multi_byte_chars.push(mbc); } - - // Assume control characters are zero width. - // FIXME: How can we decide between `width` and `width_cjk`? - let char_width = UnicodeWidthChar::width(c).unwrap_or(0); - - if char_width != 1 { - non_narrow_chars.push(NonNarrowChar::new(pos, char_width)); - } } i += char_len; diff --git a/compiler/rustc_span/src/analyze_source_file/tests.rs b/compiler/rustc_span/src/analyze_source_file/tests.rs index 0c77d080c17a..e4a24239d8ea 100644 --- a/compiler/rustc_span/src/analyze_source_file/tests.rs +++ b/compiler/rustc_span/src/analyze_source_file/tests.rs @@ -4,11 +4,10 @@ macro_rules! test { (case: $test_name:ident, text: $text:expr, lines: $lines:expr, - multi_byte_chars: $multi_byte_chars:expr, - non_narrow_chars: $non_narrow_chars:expr,) => { + multi_byte_chars: $multi_byte_chars:expr,) => { #[test] fn $test_name() { - let (lines, multi_byte_chars, non_narrow_chars) = analyze_source_file($text); + let (lines, multi_byte_chars) = analyze_source_file($text); let expected_lines: Vec = $lines.into_iter().map(RelativeBytePos).collect(); @@ -21,13 +20,6 @@ macro_rules! test { .collect(); assert_eq!(multi_byte_chars, expected_mbcs); - - let expected_nncs: Vec = $non_narrow_chars - .into_iter() - .map(|(pos, width)| NonNarrowChar::new(RelativeBytePos(pos), width)) - .collect(); - - assert_eq!(non_narrow_chars, expected_nncs); } }; } @@ -37,7 +29,6 @@ test!( text: "", lines: vec![], multi_byte_chars: vec![], - non_narrow_chars: vec![], ); test!( @@ -45,7 +36,6 @@ test!( text: "a\nc", lines: vec![0, 2], multi_byte_chars: vec![], - non_narrow_chars: vec![], ); test!( @@ -53,7 +43,6 @@ test!( text: "012345678\nabcdef012345678\na", lines: vec![0, 10, 26], multi_byte_chars: vec![], - non_narrow_chars: vec![], ); test!( @@ -61,7 +50,6 @@ test!( text: "01234β789\nbcdef0123456789abcdef", lines: vec![0, 11], multi_byte_chars: vec![(5, 2)], - non_narrow_chars: vec![], ); test!( @@ -69,7 +57,6 @@ test!( text: "01234\u{07}6789\nbcdef0123456789abcdef", lines: vec![0, 11], multi_byte_chars: vec![], - non_narrow_chars: vec![(5, 0)], ); test!( @@ -77,7 +64,6 @@ test!( text: "aβc", lines: vec![0], multi_byte_chars: vec![(1, 2)], - non_narrow_chars: vec![], ); test!( @@ -85,7 +71,6 @@ test!( text: "0123456789abcΔf012345β", lines: vec![0], multi_byte_chars: vec![(13, 2), (22, 2)], - non_narrow_chars: vec![], ); test!( @@ -93,7 +78,6 @@ test!( text: "0123456789abcdeΔ123456789abcdef01234", lines: vec![0], multi_byte_chars: vec![(15, 2)], - non_narrow_chars: vec![], ); test!( @@ -101,7 +85,6 @@ test!( text: "0123456789abcdeΔ....", lines: vec![0], multi_byte_chars: vec![(15, 2)], - non_narrow_chars: vec![], ); test!( @@ -109,7 +92,6 @@ test!( text: "0\t2", lines: vec![0], multi_byte_chars: vec![], - non_narrow_chars: vec![(1, 4)], ); test!( @@ -117,7 +99,6 @@ test!( text: "01\t3456789abcdef01234567\u{07}9", lines: vec![0], multi_byte_chars: vec![], - non_narrow_chars: vec![(2, 4), (24, 0)], ); test!( @@ -125,5 +106,4 @@ test!( text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf", lines: vec![0, 7, 27], multi_byte_chars: vec![(13, 2), (29, 2)], - non_narrow_chars: vec![(2, 4), (24, 0)], ); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 266956d63d71..ea57c1ce8185 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1345,68 +1345,6 @@ pub struct MultiByteChar { pub bytes: u8, } -/// Identifies an offset of a non-narrow character in a `SourceFile`. -#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)] -pub enum NonNarrowChar { - /// Represents a zero-width character. - ZeroWidth(RelativeBytePos), - /// Represents a wide (full-width) character. - Wide(RelativeBytePos), - /// Represents a tab character, represented visually with a width of 4 characters. - Tab(RelativeBytePos), -} - -impl NonNarrowChar { - fn new(pos: RelativeBytePos, width: usize) -> Self { - match width { - 0 => NonNarrowChar::ZeroWidth(pos), - 2 => NonNarrowChar::Wide(pos), - 4 => NonNarrowChar::Tab(pos), - _ => panic!("width {width} given for non-narrow character"), - } - } - - /// Returns the relative offset of the character in the `SourceFile`. - pub fn pos(&self) -> RelativeBytePos { - match *self { - NonNarrowChar::ZeroWidth(p) | NonNarrowChar::Wide(p) | NonNarrowChar::Tab(p) => p, - } - } - - /// Returns the width of the character, 0 (zero-width) or 2 (wide). - pub fn width(&self) -> usize { - match *self { - NonNarrowChar::ZeroWidth(_) => 0, - NonNarrowChar::Wide(_) => 2, - NonNarrowChar::Tab(_) => 4, - } - } -} - -impl Add for NonNarrowChar { - type Output = Self; - - fn add(self, rhs: RelativeBytePos) -> Self { - match self { - NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs), - NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs), - NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs), - } - } -} - -impl Sub for NonNarrowChar { - type Output = Self; - - fn sub(self, rhs: RelativeBytePos) -> Self { - match self { - NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs), - NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs), - NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs), - } - } -} - /// Identifies an offset of a character that was normalized away from `SourceFile`. #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)] pub struct NormalizedPos { @@ -1581,8 +1519,6 @@ pub struct SourceFile { pub lines: FreezeLock, /// Locations of multi-byte characters in the source code. pub multibyte_chars: Vec, - /// Width of characters that are not narrow in the source code. - pub non_narrow_chars: Vec, /// Locations of characters removed during normalization. pub normalized_pos: Vec, /// A hash of the filename & crate-id, used for uniquely identifying source @@ -1604,7 +1540,6 @@ impl Clone for SourceFile { source_len: self.source_len, lines: self.lines.clone(), multibyte_chars: self.multibyte_chars.clone(), - non_narrow_chars: self.non_narrow_chars.clone(), normalized_pos: self.normalized_pos.clone(), stable_id: self.stable_id, cnum: self.cnum, @@ -1679,7 +1614,6 @@ impl Encodable for SourceFile { } self.multibyte_chars.encode(s); - self.non_narrow_chars.encode(s); self.stable_id.encode(s); self.normalized_pos.encode(s); self.cnum.encode(s); @@ -1706,7 +1640,6 @@ impl Decodable for SourceFile { } }; let multibyte_chars: Vec = Decodable::decode(d); - let non_narrow_chars: Vec = Decodable::decode(d); let stable_id = Decodable::decode(d); let normalized_pos: Vec = Decodable::decode(d); let cnum: CrateNum = Decodable::decode(d); @@ -1721,7 +1654,6 @@ impl Decodable for SourceFile { external_src: FreezeLock::frozen(ExternalSource::Unneeded), lines: FreezeLock::new(lines), multibyte_chars, - non_narrow_chars, normalized_pos, stable_id, cnum, @@ -1809,8 +1741,7 @@ impl SourceFile { let source_len = src.len(); let source_len = u32::try_from(source_len).map_err(|_| OffsetOverflowError)?; - let (lines, multibyte_chars, non_narrow_chars) = - analyze_source_file::analyze_source_file(&src); + let (lines, multibyte_chars) = analyze_source_file::analyze_source_file(&src); Ok(SourceFile { name, @@ -1821,7 +1752,6 @@ impl SourceFile { source_len: RelativeBytePos::from_u32(source_len), lines: FreezeLock::frozen(SourceFileLines::Lines(lines)), multibyte_chars, - non_narrow_chars, normalized_pos, stable_id, cnum: LOCAL_CRATE, @@ -2130,41 +2060,44 @@ impl SourceFile { let pos = self.relative_position(pos); let (line, col_or_chpos) = self.lookup_file_pos(pos); if line > 0 { - let col = col_or_chpos; - let linebpos = self.lines()[line - 1]; - let col_display = { - let start_width_idx = self - .non_narrow_chars - .binary_search_by_key(&linebpos, |x| x.pos()) - .unwrap_or_else(|x| x); - let end_width_idx = self - .non_narrow_chars - .binary_search_by_key(&pos, |x| x.pos()) - .unwrap_or_else(|x| x); - let special_chars = end_width_idx - start_width_idx; - let non_narrow: usize = self.non_narrow_chars[start_width_idx..end_width_idx] - .iter() - .map(|x| x.width()) - .sum(); - col.0 - special_chars + non_narrow + let Some(code) = self.get_line(line - 1) else { + // If we don't have the code available, it is ok as a fallback to return the bytepos + // instead of the "display" column, which is only used to properly show underlines + // in the terminal. + // FIXME: we'll want better handling of this in the future for the sake of tools + // that want to use the display col instead of byte offsets to modify Rust code, but + // that is a problem for another day, the previous code was already incorrect for + // both displaying *and* third party tools using the json output naïvely. + tracing::info!("couldn't find line {line} {:?}", self.name); + return (line, col_or_chpos, col_or_chpos.0); }; - (line, col, col_display) + let display_col = code.chars().take(col_or_chpos.0).map(|ch| char_width(ch)).sum(); + (line, col_or_chpos, display_col) } else { - let chpos = col_or_chpos; - let col_display = { - let end_width_idx = self - .non_narrow_chars - .binary_search_by_key(&pos, |x| x.pos()) - .unwrap_or_else(|x| x); - let non_narrow: usize = - self.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum(); - chpos.0 - end_width_idx + non_narrow - }; - (0, chpos, col_display) + // This is never meant to happen? + (0, col_or_chpos, col_or_chpos.0) } } } +pub fn char_width(ch: char) -> usize { + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now, + // just accept that sometimes the code line will be longer than desired. + match ch { + '\t' => 4, + // Keep the following list in sync with `rustc_errors::emitter::OUTPUT_REPLACEMENTS`. These + // are control points that we replace before printing with a visible codepoint for the sake + // of being able to point at them with underlines. + '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}' + | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}' + | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}' + | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}' + | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}' + | '\u{007F}' => 1, + _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1), + } +} + /// Normalizes the source code and records the normalizations. fn normalize_src(src: &mut String) -> Vec { let mut normalized_pos = vec![]; diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index fb212d67997a..14c157a0111c 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -330,7 +330,6 @@ impl SourceMap { cnum: CrateNum, file_local_lines: FreezeLock, multibyte_chars: Vec, - non_narrow_chars: Vec, normalized_pos: Vec, metadata_index: u32, ) -> Lrc { @@ -348,7 +347,6 @@ impl SourceMap { source_len, lines: file_local_lines, multibyte_chars, - non_narrow_chars, normalized_pos, stable_id, cnum, diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index dcb02da37192..0c818b94b85a 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -232,7 +232,6 @@ fn t10() { source_len, lines, multibyte_chars, - non_narrow_chars, normalized_pos, stable_id, .. @@ -246,7 +245,6 @@ fn t10() { CrateNum::ZERO, FreezeLock::new(lines.read().clone()), multibyte_chars, - non_narrow_chars, normalized_pos, 0, ); diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr index 1ed455422511..09d78b2f3467 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr @@ -2,7 +2,7 @@ error[E0765]: unterminated double quote string --> $DIR/test-compile-fail3.rs:3:1 | 3 | "fail - | ^^^^^^ + | ^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/codemap_tests/tab_2.stderr b/tests/ui/codemap_tests/tab_2.stderr index 4f9a937155dd..b22c7b426651 100644 --- a/tests/ui/codemap_tests/tab_2.stderr +++ b/tests/ui/codemap_tests/tab_2.stderr @@ -4,7 +4,7 @@ error[E0765]: unterminated double quote string LL | """; | ___________________^ LL | | } - | |__^ + | |_^ error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0601.stderr b/tests/ui/error-codes/E0601.stderr index 41a4a8f7dbba..c051bc0b31a0 100644 --- a/tests/ui/error-codes/E0601.stderr +++ b/tests/ui/error-codes/E0601.stderr @@ -2,7 +2,7 @@ error[E0601]: `main` function not found in crate `E0601` --> $DIR/E0601.rs:1:37 | LL | - | ^ consider adding a `main` function to `$DIR/E0601.rs` + | ^ consider adding a `main` function to `$DIR/E0601.rs` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-44078.stderr b/tests/ui/issues/issue-44078.stderr index 3e12de34e11e..41106b29aad7 100644 --- a/tests/ui/issues/issue-44078.stderr +++ b/tests/ui/issues/issue-44078.stderr @@ -4,7 +4,7 @@ error[E0765]: unterminated double quote string LL | "😊""; | _________^ LL | | } - | |__^ + | |_^ error: aborting due to 1 previous error diff --git a/tests/ui/lexer/unterminated-comment.stderr b/tests/ui/lexer/unterminated-comment.stderr index ea65bffd1036..6ab5441ee05c 100644 --- a/tests/ui/lexer/unterminated-comment.stderr +++ b/tests/ui/lexer/unterminated-comment.stderr @@ -2,7 +2,7 @@ error[E0758]: unterminated block comment --> $DIR/unterminated-comment.rs:1:1 | LL | /* - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/lexer/unterminated-nested-comment.stderr b/tests/ui/lexer/unterminated-nested-comment.stderr index 9117b689c94e..78b72ce1fe4a 100644 --- a/tests/ui/lexer/unterminated-nested-comment.stderr +++ b/tests/ui/lexer/unterminated-nested-comment.stderr @@ -12,7 +12,7 @@ LL | | /* | | | | | ...as last nested comment starts here, maybe you want to close this instead? LL | | */ - | |_--^ + | |_-^ | | | ...and last nested comment terminates here. diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr index 1f3d40605f67..584902ee4c03 100644 --- a/tests/ui/lint/issue-104897.stderr +++ b/tests/ui/lint/issue-104897.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-104897.rs:5:18 | LL | fn f(){(print!(á - | -- - ^ + | -- - ^ | || | | || unclosed delimiter | |unclosed delimiter diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr index ad90aeda1d13..d9748843fd7a 100644 --- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr +++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11 | LL | fn a(){{{ - | --- ^ + | ---^ | ||| | ||unclosed delimiter | |unclosed delimiter diff --git a/tests/ui/parser/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr index 38889da5da12..1fb324a1b7e8 100644 --- a/tests/ui/parser/bad-char-literals.stderr +++ b/tests/ui/parser/bad-char-literals.stderr @@ -37,12 +37,12 @@ error: character literal may only contain one codepoint --> $DIR/bad-char-literals.rs:18:5 | LL | '-␀-'; - | ^^^^ + | ^^^^^ | help: if you meant to write a string literal, use double quotes | LL | "-␀-"; - | ~ ~ + | ~ ~ error: character constant must be escaped: `\t` --> $DIR/bad-char-literals.rs:21:6 diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index 7182d86d001d..d76cb25ad8b8 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -31,7 +31,7 @@ LL | && let () = () LL | } | - ...as it matches this but it has different indentation LL | } - | ^ + | ^ error: found a `{` in the middle of a let-chain --> $DIR/brace-in-let-chain.rs:14:24 diff --git a/tests/ui/parser/byte-string-literals.stderr b/tests/ui/parser/byte-string-literals.stderr index 655b6998e85f..24e0eaac8fa9 100644 --- a/tests/ui/parser/byte-string-literals.stderr +++ b/tests/ui/parser/byte-string-literals.stderr @@ -43,7 +43,7 @@ error[E0766]: unterminated double quote byte string LL | b"a | ______^ LL | | } - | |__^ + | |_^ error: aborting due to 6 previous errors diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr index 78f5d7b63b95..d17913eb7ea4 100644 --- a/tests/ui/parser/deli-ident-issue-1.stderr +++ b/tests/ui/parser/deli-ident-issue-1.stderr @@ -11,7 +11,7 @@ LL | } | - ...as it matches this but it has different indentation ... LL | fn main() { } - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-103451.stderr b/tests/ui/parser/issues/issue-103451.stderr index 7ad816e451ea..f078e556e2b1 100644 --- a/tests/ui/parser/issues/issue-103451.stderr +++ b/tests/ui/parser/issues/issue-103451.stderr @@ -4,7 +4,7 @@ error: this file contains an unclosed delimiter LL | struct S { | - unclosed delimiter LL | x: [u8; R - | - ^ + | - ^ | | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr index e6e76535761f..c067d12e2d96 100644 --- a/tests/ui/parser/issues/issue-104367.stderr +++ b/tests/ui/parser/issues/issue-104367.stderr @@ -20,7 +20,7 @@ LL | #![cfg] { LL | #![w,) | - missing open `(` for this delimiter LL | - | ^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr index c75eafa18335..72017e4327de 100644 --- a/tests/ui/parser/issues/issue-105209.stderr +++ b/tests/ui/parser/issues/issue-105209.stderr @@ -16,7 +16,7 @@ LL | #![c={#![c[)x | | unclosed delimiter | unclosed delimiter LL | - | ^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-107705.stderr b/tests/ui/parser/issues/issue-107705.stderr index 2d0c3e0e675c..10a47b799318 100644 --- a/tests/ui/parser/issues/issue-107705.stderr +++ b/tests/ui/parser/issues/issue-107705.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-107705.rs:3:67 | LL | fn f() {a(b:&, - | - - unclosed delimiter ^ + | - - unclosed delimiter ^ | | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-2354.stderr b/tests/ui/parser/issues/issue-2354.stderr index fd649a575c6c..3e63473b6f45 100644 --- a/tests/ui/parser/issues/issue-2354.stderr +++ b/tests/ui/parser/issues/issue-2354.stderr @@ -10,7 +10,7 @@ LL | } | - ...as it matches this but it has different indentation ... LL | - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr index 6889cb3b8e9d..6435cb2b719f 100644 --- a/tests/ui/parser/issues/issue-62546.stderr +++ b/tests/ui/parser/issues/issue-62546.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-62546.rs:1:60 | LL | pub t(# - | - unclosed delimiter ^ + | - unclosed delimiter ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr index 37314dd39c7f..d4aaef161813 100644 --- a/tests/ui/parser/issues/issue-62554.stderr +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-62554.rs:5:89 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { - | - - - - - ^ + | - - - - -^ | | | | | | | | | | | unclosed delimiter | | | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr index 2165a81a0482..d8ae2cf09053 100644 --- a/tests/ui/parser/issues/issue-62881.stderr +++ b/tests/ui/parser/issues/issue-62881.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-62881.rs:3:96 | LL | fn f() -> isize { fn f() -> isize {} pub f< - | - unclosed delimiter ^ + | - unclosed delimiter ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr index 870633fc96f8..230319fc31e7 100644 --- a/tests/ui/parser/issues/issue-62894.stderr +++ b/tests/ui/parser/issues/issue-62894.stderr @@ -8,7 +8,7 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! | unclosed delimiter LL | LL | fn main() {} - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr index 14411a8cb784..493183988e18 100644 --- a/tests/ui/parser/issues/issue-62973.stderr +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -25,7 +25,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter LL | LL | - | ^ + | ^ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr index 27c94f337bdb..e0f7dd176ceb 100644 --- a/tests/ui/parser/issues/issue-63116.stderr +++ b/tests/ui/parser/issues/issue-63116.stderr @@ -10,7 +10,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-63116.rs:3:18 | LL | impl W $DIR/issue-63135.rs:3:16 | LL | fn i(n{...,f # - | - - ^ + | - - ^ | | | | | unclosed delimiter | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index 4be992d58460..ba38c4fa1b7a 100644 --- a/tests/ui/parser/issues/issue-66473.stderr +++ b/tests/ui/parser/issues/issue-66473.stderr @@ -8,7 +8,7 @@ error: unknown start of token: \u{0} --> $DIR/issue-66473.rs:4:3 | LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ - | ^ + | ^^^^^^^^^^^^^^^^^^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used = note: character appears 17 more times @@ -17,19 +17,19 @@ error: unknown start of token: \u{1d} --> $DIR/issue-66473.rs:5:2 | LL | ␋␝6␝␀␀ - | ^ + | ^ error: unknown start of token: \u{1d} --> $DIR/issue-66473.rs:5:4 | LL | ␋␝6␝␀␀ - | ^ + | ^ error: unknown start of token: \u{0} --> $DIR/issue-66473.rs:5:5 | LL | ␋␝6␝␀␀ - | ^ + | ^^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used = note: character appears once more @@ -40,7 +40,7 @@ error: expected one of `!` or `[`, found `6` LL | #͈␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀ | - expected one of `!` or `[` LL | ␋␝6␝␀␀ - | ^ unexpected token + | ^ unexpected token error: aborting due to 6 previous errors diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr index 9f631edf680c..b82b0f3255b5 100644 --- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr +++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr @@ -41,7 +41,7 @@ LL | V = [Vec::new; { [0].len() ].len() as isize, | - missing open `[` for this delimiter ... LL | fn main() {} - | ^ + | ^ error: aborting due to 4 previous errors diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr index ccb0624208b2..f003f3781795 100644 --- a/tests/ui/parser/issues/issue-68629.stderr +++ b/tests/ui/parser/issues/issue-68629.stderr @@ -8,13 +8,13 @@ error: unknown start of token: \u{1f} --> $DIR/issue-68629.rs:4:2 | LL | ␜␟ts␀![{i - | ^ + | ^ error: unknown start of token: \u{0} --> $DIR/issue-68629.rs:4:5 | LL | ␜␟ts␀![{i - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -22,7 +22,7 @@ error: unknown start of token: \u{0} --> $DIR/issue-68629.rs:5:1 | LL | ␀␀ fn rݻoa>rݻm - | ^ + | ^^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used = note: character appears once more @@ -31,11 +31,11 @@ error: this file contains an unclosed delimiter --> $DIR/issue-68629.rs:5:17 | LL | ␜␟ts␀![{i - | -- unclosed delimiter - | | - | unclosed delimiter + | -- unclosed delimiter + | | + | unclosed delimiter LL | ␀␀ fn rݻoa>rݻm - | ^ + | ^ error: aborting due to 5 previous errors diff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr index 6025ea8c1ae7..9bd98287db34 100644 --- a/tests/ui/parser/issues/issue-68730.stderr +++ b/tests/ui/parser/issues/issue-68730.stderr @@ -10,7 +10,7 @@ error: unknown start of token: \u{0} --> $DIR/issue-68730.rs:5:8 | LL | enum␀em␀˂˂ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -18,30 +18,30 @@ error: unknown start of token: \u{2c2} --> $DIR/issue-68730.rs:5:9 | LL | enum␀em␀˂˂ - | ^^ + | ^^ | = note: character appears once more help: Unicode character '˂' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not | LL | enum␀em␀<< - | ~~ + | ~~ error: unknown start of token: \u{2c2} --> $DIR/issue-68730.rs:5:10 | LL | enum␀em␀˂˂ - | ^ + | ^ | help: Unicode character '˂' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not | LL | enum␀em␀˂< - | ~ + | ~ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` --> $DIR/issue-68730.rs:5:10 | LL | enum␀em␀˂˂ - | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime error: aborting due to 5 previous errors diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr index de3b33ecd95c..6caaaa792b19 100644 --- a/tests/ui/parser/issues/issue-81804.stderr +++ b/tests/ui/parser/issues/issue-81804.stderr @@ -10,7 +10,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-81804.rs:6:11 | LL | fn p([=(} - | -- ^ + | -- ^ | || | |unclosed delimiter | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr index 63d135f73e69..d12c74b4a342 100644 --- a/tests/ui/parser/issues/issue-81827.stderr +++ b/tests/ui/parser/issues/issue-81827.stderr @@ -11,7 +11,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-81827.rs:10:27 | LL | fn r()->i{0|{#[cfg(r(0{]0 - | - - - ^ + | - - - ^ | | | | | | | missing open `[` for this delimiter | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr index e866d3922675..b9b14c081a98 100644 --- a/tests/ui/parser/issues/issue-84104.stderr +++ b/tests/ui/parser/issues/issue-84104.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-84104.rs:2:13 | LL | #[i=i::<ښܖ< - | - ^ + | - ^ | | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr index d9b6b336a2ce..b30f3d9114c1 100644 --- a/tests/ui/parser/issues/issue-84148-2.stderr +++ b/tests/ui/parser/issues/issue-84148-2.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-84148-2.rs:2:16 | LL | fn f(t:for<>t? - | - ^ + | - ^ | | | unclosed delimiter diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr index 60ef025fa8bf..5b54072d009f 100644 --- a/tests/ui/parser/issues/issue-88770.stderr +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -8,7 +8,7 @@ LL | fn m(){print!("",(c for&g | unclosed delimiter ... LL | e - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index 97aac661d465..39144246be24 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -5,7 +5,7 @@ LL | impl T for () { | - unclosed delimiter ... LL | - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr index f70dac443e55..603aee02ad6b 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr @@ -5,7 +5,7 @@ LL | pub(crate) struct Bar { | - unclosed delimiter ... LL | fn main() {} - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index a565ad49b221..a2fb698c80f6 100644 --- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -5,7 +5,7 @@ LL | trait T { | - unclosed delimiter ... LL | fn main() {} - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/parser-ice-ed2021-await-105210.stderr b/tests/ui/parser/parser-ice-ed2021-await-105210.stderr index fc54476c2204..29abab2608e9 100644 --- a/tests/ui/parser/parser-ice-ed2021-await-105210.stderr +++ b/tests/ui/parser/parser-ice-ed2021-await-105210.stderr @@ -28,7 +28,7 @@ LL | (( h (const {( default ( await ( await ( (move {await((((}} | unclosed delimiter ... LL | - | ^ + | ^ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr index 8162db3d8e5d..4ed40d753261 100644 --- a/tests/ui/parser/parser-recovery-1.stderr +++ b/tests/ui/parser/parser-recovery-1.stderr @@ -10,7 +10,7 @@ LL | } | - ...as it matches this but it has different indentation ... LL | } - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr index 3150570e1c90..e235a1583849 100644 --- a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr +++ b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr @@ -8,13 +8,13 @@ error: bare CR not allowed in doc-comment --> $DIR/several-carriage-returns-in-doc-comment.rs:6:32 | LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols - | ^ + | ^ error: bare CR not allowed in doc-comment --> $DIR/several-carriage-returns-in-doc-comment.rs:6:52 | LL | /// This do␍c comment contains ␍three isolated `\r`␍ symbols - | ^ + | ^ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr index d40b982da7c3..9fdad87a86cf 100644 --- a/tests/ui/parser/unbalanced-doublequote.stderr +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -3,7 +3,7 @@ error[E0765]: unterminated double quote string | LL | / " LL | | } - | |__^ + | |_^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/unclosed-braces.stderr b/tests/ui/parser/unclosed-braces.stderr index acd92ac79259..74ac66af528d 100644 --- a/tests/ui/parser/unclosed-braces.stderr +++ b/tests/ui/parser/unclosed-braces.stderr @@ -11,7 +11,7 @@ LL | } | - ...as it matches this but it has different indentation ... LL | - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr index c6960892b2bc..192f5324935f 100644 --- a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr +++ b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/unmatched-delimiter-at-end-of-file.rs:11:63 | LL | fn foo() { - | - unclosed delimiter ^ + | - unclosed delimiter ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr index 6e624cb91316..1e62a0a06a36 100644 --- a/tests/ui/parser/use-unclosed-brace.stderr +++ b/tests/ui/parser/use-unclosed-brace.stderr @@ -5,7 +5,7 @@ LL | use foo::{bar, baz; | - unclosed delimiter ... LL | fn main() {} - | ^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr index 28cf6d97e96c..55ebf7aacd23 100644 --- a/tests/ui/parser/utf16-be-without-bom.stderr +++ b/tests/ui/parser/utf16-be-without-bom.stderr @@ -10,7 +10,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:3 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -18,7 +18,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:5 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -26,7 +26,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:7 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -34,7 +34,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:9 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -42,7 +42,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:11 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -50,7 +50,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:13 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -58,7 +58,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:15 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -66,7 +66,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:17 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -74,7 +74,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:19 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -82,7 +82,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:21 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -90,7 +90,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:23 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -98,7 +98,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-be-without-bom.rs:4:25 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -106,12 +106,12 @@ error: expected one of `!` or `::`, found `n` --> $DIR/utf16-be-without-bom.rs:4:4 | LL | ␀f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ expected one of `!` or `::` + | ^ expected one of `!` or `::` | help: consider removing the space to spell keyword `fn` | LL | ␀fn␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ~~ + | ~~ error: aborting due to 14 previous errors diff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr index 53004ac942d9..ad272a70f062 100644 --- a/tests/ui/parser/utf16-le-without-bom.stderr +++ b/tests/ui/parser/utf16-le-without-bom.stderr @@ -10,7 +10,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:4 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -18,7 +18,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:6 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -26,7 +26,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:8 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -34,7 +34,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:10 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -42,7 +42,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:12 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -50,7 +50,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:14 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -58,7 +58,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:16 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -66,7 +66,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:18 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -74,7 +74,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:20 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -82,7 +82,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:22 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -90,7 +90,7 @@ error: unknown start of token: \u{0} --> $DIR/utf16-le-without-bom.rs:4:24 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ + | ^ | = help: source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used @@ -106,7 +106,7 @@ error: expected one of `!` or `::`, found `n` --> $DIR/utf16-le-without-bom.rs:4:3 | LL | f␀n␀ ␀m␀a␀i␀n␀(␀)␀ ␀{␀}␀ - | ^ expected one of `!` or `::` + | ^ expected one of `!` or `::` | help: consider removing the space to spell keyword `fn` | diff --git a/tests/ui/rustdoc/unterminated-doc-comment.stderr b/tests/ui/rustdoc/unterminated-doc-comment.stderr index 2d96c606b163..f0b691333dc9 100644 --- a/tests/ui/rustdoc/unterminated-doc-comment.stderr +++ b/tests/ui/rustdoc/unterminated-doc-comment.stderr @@ -2,7 +2,7 @@ error[E0758]: unterminated block doc-comment --> $DIR/unterminated-doc-comment.rs:1:1 | LL | /*! - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr index 004a057bbcda..c8cce1624161 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -2,7 +2,7 @@ error: this file contains an unclosed delimiter --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:12:85 | LL | trait C{async fn new(val: T) {} - | - unclosed delimiter ^ + | - unclosed delimiter ^ error: aborting due to 1 previous error diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr index 599c8de97578..4c8ee6bc013e 100644 --- a/tests/ui/str/str-escape.stderr +++ b/tests/ui/str/str-escape.stderr @@ -23,8 +23,8 @@ warning: whitespace symbol '\u{c}' is not skipped LL | let s = b"a\ | ________________^ LL | | ␌b"; - | | ^- whitespace symbol '\u{c}' is not skipped - | |____| + | | ^ whitespace symbol '\u{c}' is not skipped + | |_____| | warning: 3 warnings emitted diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr index b3440e46e8ac..3d73ee1d27a0 100644 --- a/tests/ui/suggestions/issue-94171.stderr +++ b/tests/ui/suggestions/issue-94171.stderr @@ -30,7 +30,7 @@ LL | (; {` | unclosed delimiter ... LL | - | ^ + | ^ error: aborting due to 3 previous errors diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr index 7cb30eea530c..01e34919ce67 100644 --- a/tests/ui/typeck/issue-91334.stderr +++ b/tests/ui/typeck/issue-91334.stderr @@ -11,7 +11,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-91334.rs:7:23 | LL | fn f(){||yield(((){), - | - - - ^ + | - - - ^ | | | | | | | missing open `(` for this delimiter | | unclosed delimiter From 9dffe9573be86ac7302fb2f27219ef8f9c78dea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Jul 2024 20:02:08 +0000 Subject: [PATCH 21/49] =?UTF-8?q?Make=20unicode=20text=20flow=20control=20?= =?UTF-8?q?chars=20visible=20as=20=EF=BF=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already point these out quite aggressively, telling people not to use them, but would normally be rendered as nothing. Having them visible will make it easier for people to actually deal with them. ``` error: unicode codepoint changing visible direction of text present in literal --> $DIR/unicode-control-codepoints.rs:26:22 | LL | println!("{:?}", '�'); | ^-^ | || | |'\u{202e}' | this literal contains an invisible unicode text flow control codepoint | = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen = help: if their presence wasn't intentional, you can remove them help: if you want to keep them but make them visible in your source code, you can escape them | LL | println!("{:?}", '\u{202e}'); | ~~~~~~~~ ``` vs the previous ``` error: unicode codepoint changing visible direction of text present in literal --> $DIR/unicode-control-codepoints.rs:26:22 | LL | println!("{:?}", ''); | ^- | || | |'\u{202e}' | this literal contains an invisible unicode text flow control codepoint | = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen = help: if their presence wasn't intentional, you can remove them help: if you want to keep them but make them visible in your source code, you can escape them | LL | println!("{:?}", '\u{202e}'); | ~~~~~~~~ ``` --- compiler/rustc_errors/src/emitter.rs | 21 ++-- compiler/rustc_span/src/lib.rs | 3 +- .../parser/unicode-control-codepoints.stderr | 98 +++++++++---------- 3 files changed, 62 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 16fa0ff7a2d6..58220c654900 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2558,18 +2558,19 @@ fn num_decimal_digits(num: usize) -> usize { } // We replace some characters so the CLI output is always consistent and underlines aligned. +// Keep the following list in sync with `rustc_span::char_width`. const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ - ('\t', " "), // We do our own tab replacement + ('\t', " "), // We do our own tab replacement ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. - ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently - ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk - ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always. - ('\u{202E}', ""), - ('\u{2066}', ""), - ('\u{2067}', ""), - ('\u{2068}', ""), - ('\u{202C}', ""), - ('\u{2069}', ""), + ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently + ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk + ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always. + ('\u{202E}', "�"), + ('\u{2066}', "�"), + ('\u{2067}', "�"), + ('\u{2068}', "�"), + ('\u{202C}', "�"), + ('\u{2069}', "�"), // In terminals without Unicode support the following will be garbled, but in *all* terminals // the underlying codepoint will be as well. We could gate this replacement behind a "unicode // support" gate. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea57c1ce8185..7c8ac3be4bec 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2093,7 +2093,8 @@ pub fn char_width(ch: char) -> usize { | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}' | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}' | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}' - | '\u{007F}' => 1, + | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}' + | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1, _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1), } } diff --git a/tests/ui/parser/unicode-control-codepoints.stderr b/tests/ui/parser/unicode-control-codepoints.stderr index fc071a941914..28de4ae72abb 100644 --- a/tests/ui/parser/unicode-control-codepoints.stderr +++ b/tests/ui/parser/unicode-control-codepoints.stderr @@ -17,78 +17,78 @@ LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:26 | -LL | println!("{:?}", b"/* } if isAdmin begin admins only "); +LL | println!("{:?}", b"/*� } �if isAdmin� � begin admins only "); | ^ must be ASCII but is '\u{202e}' | help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes | -LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only "); +LL | println!("{:?}", b"/*\xE2\x80\xAE } �if isAdmin� � begin admins only "); | ~~~~~~~~~~~~ error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:30 | -LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ must be ASCII but is '\u{2066}' +LL | println!("{:?}", b"/*� } �if isAdmin� � begin admins only "); + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | -LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only "); - | ~~~~~~~~~~~~ +LL | println!("{:?}", b"/*� } \xE2\x81\xA6if isAdmin� � begin admins only "); + | ~~~~~~~~~~~~ error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:41 | -LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ must be ASCII but is '\u{2069}' +LL | println!("{:?}", b"/*� } �if isAdmin� � begin admins only "); + | ^ must be ASCII but is '\u{2069}' | help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes | -LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only "); - | ~~~~~~~~~~~~ +LL | println!("{:?}", b"/*� } �if isAdmin\xE2\x81\xA9 � begin admins only "); + | ~~~~~~~~~~~~ error: non-ASCII character in byte string literal --> $DIR/unicode-control-codepoints.rs:16:43 | -LL | println!("{:?}", b"/* } if isAdmin begin admins only "); - | ^ must be ASCII but is '\u{2066}' +LL | println!("{:?}", b"/*� } �if isAdmin� � begin admins only "); + | ^ must be ASCII but is '\u{2066}' | help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes | -LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only "); - | ~~~~~~~~~~~~ +LL | println!("{:?}", b"/*� } �if isAdmin� \xE2\x81\xA6 begin admins only "); + | ~~~~~~~~~~~~ error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:29 | -LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); +LL | println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##); | ^ must be ASCII but is '\u{202e}' error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:33 | -LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); - | ^ must be ASCII but is '\u{2066}' +LL | println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##); + | ^ must be ASCII but is '\u{2066}' error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:44 | -LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); - | ^ must be ASCII but is '\u{2069}' +LL | println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##); + | ^ must be ASCII but is '\u{2069}' error: non-ASCII character in raw byte string literal --> $DIR/unicode-control-codepoints.rs:21:46 | -LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); - | ^ must be ASCII but is '\u{2066}' +LL | println!("{:?}", br##"/*� } �if isAdmin� � begin admins only "##); + | ^ must be ASCII but is '\u{2066}' error: unicode codepoint changing visible direction of text present in comment --> $DIR/unicode-control-codepoints.rs:2:5 | -LL | // if access_level != "user" { // Check if admin - | ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ - | | || - | | |'\u{202a}' +LL | // if access_level != "us�e�r" { // Check if admin + | ^^^^^^^^^^^^^^^^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | '\u{202a}' | | '\u{202b}' | this comment contains invisible unicode text flow control codepoints | @@ -99,12 +99,12 @@ LL | // if access_level != "user" { // Check if admin error: unicode codepoint changing visible direction of text present in comment --> $DIR/unicode-control-codepoints.rs:30:1 | -LL | //"/* } if isAdmin begin admins only */" - | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ - | | | | || - | | | | |'\u{2066}' - | | | | '\u{2069}' - | | | '\u{2066}' +LL | //"/*� } �if isAdmin� � begin admins only */" + | ^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^ + | | | | | | + | | | | | '\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' | | '\u{202e}' | this comment contains invisible unicode text flow control codepoints | @@ -114,12 +114,12 @@ LL | //"/* } if isAdmin begin admins only */" error: unicode codepoint changing visible direction of text present in literal --> $DIR/unicode-control-codepoints.rs:11:22 | -LL | println!("{:?}", "/* } if isAdmin begin admins only "); - | ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^ - | | | | || - | | | | |'\u{2066}' - | | | | '\u{2069}' - | | | '\u{2066}' +LL | println!("{:?}", "/*� } �if isAdmin� � begin admins only "); + | ^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^ + | | | | | | + | | | | | '\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' | | '\u{202e}' | this literal contains invisible unicode text flow control codepoints | @@ -134,12 +134,12 @@ LL | println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begi error: unicode codepoint changing visible direction of text present in literal --> $DIR/unicode-control-codepoints.rs:14:22 | -LL | println!("{:?}", r##"/* } if isAdmin begin admins only "##); - | ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ - | | | | || - | | | | |'\u{2066}' - | | | | '\u{2069}' - | | | '\u{2066}' +LL | println!("{:?}", r##"/*� } �if isAdmin� � begin admins only "##); + | ^^^^^^-^^^-^^^^^^^^^^-^-^^^^^^^^^^^^^^^^^^^^^^ + | | | | | | + | | | | | '\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' | | '\u{202e}' | this literal contains invisible unicode text flow control codepoints | @@ -153,8 +153,8 @@ LL | println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} b error: unicode codepoint changing visible direction of text present in literal --> $DIR/unicode-control-codepoints.rs:26:22 | -LL | println!("{:?}", ''); - | ^- +LL | println!("{:?}", '�'); + | ^-^ | || | |'\u{202e}' | this literal contains an invisible unicode text flow control codepoint @@ -169,8 +169,8 @@ LL | println!("{:?}", '\u{202e}'); error: unicode codepoint changing visible direction of text present in doc comment --> $DIR/unicode-control-codepoints.rs:33:1 | -LL | /** ''); */fn foo() {} - | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint +LL | /** '�'); */fn foo() {} + | ^^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint | = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen = note: if their presence wasn't intentional, you can remove them @@ -181,8 +181,8 @@ error: unicode codepoint changing visible direction of text present in doc comme | LL | / /** LL | | * -LL | | * ''); */fn bar() {} - | |___________^ this doc comment contains an invisible unicode text flow control codepoint +LL | | * '�'); */fn bar() {} + | |____________^ this doc comment contains an invisible unicode text flow control codepoint | = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen = note: if their presence wasn't intentional, you can remove them From c5dadd0408bc5654f001efe0f2224ff67e5e90a7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 19 Jul 2024 11:02:59 +1000 Subject: [PATCH 22/49] Use `#[rustfmt::skip]` on some `use` groups to prevent reordering. `use` declarations will be reformatted in #125443. Very rarely, there is a desire to force a group of `use` declarations together in a way that auto-formatting will break up. E.g. when you want a single comment to apply to a group. #126776 dealt with all of these in the codebase, ensuring that no comments intended for multiple `use` declarations would end up in the wrong place. But some people were unhappy with it. This commit uses `#[rustfmt::skip]` to create these custom `use` groups in an idiomatic way for a few of the cases changed in #126776. This works because rustfmt treats any `use` item annotated with `#[rustfmt::skip]` as a barrier and won't reorder other `use` items around it. --- compiler/rustc_const_eval/src/interpret/validity.rs | 2 ++ compiler/rustc_lint/src/lib.rs | 1 + library/core/src/char/mod.rs | 5 +++++ library/core/src/unicode/mod.rs | 10 ++++++---- library/std/src/rt.rs | 2 ++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 4da7e233889f..3dc3e6c88332 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -34,6 +34,8 @@ use super::{ Pointer, Projectable, Scalar, ValueVisitor, }; +// for the validation errors +#[rustfmt::skip] use super::InterpError::UndefinedBehavior as Ub; use super::InterpError::Unsupported as Unsup; use super::UndefinedBehaviorInfo::*; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 290f91045c45..1ed0b2c0d694 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -120,6 +120,7 @@ use types::*; use unit_bindings::*; use unused::*; +#[rustfmt::skip] pub use builtin::{MissingDoc, SoftLints}; pub use context::{CheckLintNameResult, FindLintError, LintStore}; pub use context::{EarlyContext, LateContext, LintContext}; diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 3c641a2e01c9..37c27ecb8c4d 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -24,6 +24,8 @@ mod convert; mod decode; mod methods; +// stable re-exports +#[rustfmt::skip] #[stable(feature = "try_from", since = "1.34.0")] pub use self::convert::CharTryFromError; #[stable(feature = "char_from_str", since = "1.20.0")] @@ -31,11 +33,14 @@ pub use self::convert::ParseCharError; #[stable(feature = "decode_utf16", since = "1.9.0")] pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; +// perma-unstable re-exports +#[rustfmt::skip] #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf16_raw; // perma-unstable #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf8_raw; // perma-unstable +#[rustfmt::skip] use crate::ascii; use crate::error::Error; use crate::escape; diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 5ddd9f7476dd..6066aa992160 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -1,13 +1,15 @@ #![unstable(feature = "unicode_internals", issue = "none")] #![allow(missing_docs)] -// The `pub use` ones are for use in alloc, and are not re-exported in std. - -pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; +// for use in alloc, not re-exported in std. +#[rustfmt::skip] pub use unicode_data::case_ignorable::lookup as Case_Ignorable; pub use unicode_data::cased::lookup as Cased; -pub(crate) use unicode_data::cc::lookup as Cc; pub use unicode_data::conversions; + +#[rustfmt::skip] +pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; +pub(crate) use unicode_data::cc::lookup as Cc; pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; pub(crate) use unicode_data::lowercase::lookup as Lowercase; pub(crate) use unicode_data::n::lookup as N; diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index deb4a8fa7eed..307a543c9d21 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -16,9 +16,11 @@ #![deny(unsafe_op_in_unsafe_fn)] #![allow(unused_macros)] +#[rustfmt::skip] pub use crate::panicking::{begin_panic, panic_count}; pub use core::panicking::{panic_display, panic_fmt}; +#[rustfmt::skip] use crate::sync::Once; use crate::sys; use crate::thread::{self, Thread}; From ce7b069fd840916415adf2357c6133e2c1e4625b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 19 Jul 2024 16:52:33 -0700 Subject: [PATCH 23/49] compiler: Never debug_assert in codegen The gains in performance are not worth the costs in correctness. This is partly because the gains are zero and the costs are unknown. --- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- .../src/debuginfo/metadata.rs | 14 +++++----- .../src/debuginfo/metadata/enums/cpp_like.rs | 12 ++++----- .../src/debuginfo/metadata/enums/mod.rs | 4 +-- .../src/debuginfo/metadata/enums/native.rs | 4 +-- .../src/debuginfo/metadata/type_map.rs | 22 ++++++---------- .../rustc_codegen_llvm/src/debuginfo/utils.rs | 2 +- .../src/back/symbol_export.rs | 6 ++--- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../src/debuginfo/type_names.rs | 4 +-- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 4 +-- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 4 +-- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 26 +++++++++---------- .../rustc_codegen_ssa/src/traits/builder.rs | 12 ++++----- 16 files changed, 57 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 164d1681a367..80aa2018c81b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -330,7 +330,7 @@ impl<'ll> CodegenCx<'ll, '_> { // If this assertion triggers, there's something wrong with commandline // argument validation. - debug_assert!( + assert!( !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled() && self.tcx.sess.target.is_like_windows && self.tcx.sess.opts.cg.prefer_dynamic) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 851a4c42e99b..364c35f31070 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -170,7 +170,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( ) -> DINodeCreationResult<'ll> { // The debuginfo generated by this function is only valid if `ptr_type` is really just // a (fat) pointer. Make sure it is not called for e.g. `Box`. - debug_assert_eq!( + assert_eq!( cx.size_and_align_of(ptr_type), cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type)) ); @@ -185,7 +185,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( match fat_pointer_kind(cx, pointee_type) { None => { // This is a thin pointer. Create a regular pointer type and give it the correct name. - debug_assert_eq!( + assert_eq!( (data_layout.pointer_size, data_layout.pointer_align.abi), cx.size_and_align_of(ptr_type), "ptr_type={ptr_type}, pointee_type={pointee_type}", @@ -240,8 +240,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( FatPtrKind::Slice => ("data_ptr", "length"), }; - debug_assert_eq!(abi::FAT_PTR_ADDR, 0); - debug_assert_eq!(abi::FAT_PTR_EXTRA, 1); + assert_eq!(abi::FAT_PTR_ADDR, 0); + assert_eq!(abi::FAT_PTR_EXTRA, 1); // The data pointer type is a regular, thin pointer, regardless of whether this // is a slice or a trait object. @@ -498,7 +498,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D } }; - debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _); + assert_eq!(di_node_for_uid as *const _, di_node as *const _); } else { debug_context(cx).type_map.insert(unique_type_id, di_node); } @@ -1060,7 +1060,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( let ty::Adt(adt_def, _) = struct_type.kind() else { bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type); }; - debug_assert!(adt_def.is_struct()); + assert!(adt_def.is_struct()); let containing_scope = get_namespace_for_item(cx, adt_def.did()); let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); @@ -1130,7 +1130,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( } }; - debug_assert!( + assert!( up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 12f98eef97d4..cf7dddce84ff 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -204,7 +204,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( let enum_type_and_layout = cx.layout_of(enum_type); let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false); - debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); type_map::build_type_with_children( cx, @@ -279,7 +279,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let coroutine_type_and_layout = cx.layout_of(coroutine_type); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); - debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); type_map::build_type_with_children( cx, @@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( if is_128_bits { DiscrKind::Exact128(discr_val) } else { - debug_assert_eq!(discr_val, discr_val as u64 as u128); + assert_eq!(discr_val, discr_val as u64 as u128); DiscrKind::Exact(discr_val as u64) } } @@ -526,8 +526,8 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( if is_128_bits { DiscrKind::Range128(min, max) } else { - debug_assert_eq!(min, min as u64 as u128); - debug_assert_eq!(max, max as u64 as u128); + assert_eq!(min, min as u64 as u128); + assert_eq!(max, max as u64 as u128); DiscrKind::Range(min as u64, max as u64) } } @@ -815,7 +815,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( } })); - debug_assert_eq!( + assert_eq!( cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout)) ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 2b00bb14593e..96be1900ab2b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -106,7 +106,7 @@ fn tag_base_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, ) -> Ty<'tcx> { - debug_assert!(match enum_type_and_layout.ty.kind() { + assert!(match enum_type_and_layout.ty.kind() { ty::Coroutine(..) => true, ty::Adt(adt_def, _) => adt_def.is_enum(), _ => false, @@ -251,7 +251,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_layout: TyAndLayout<'tcx>, di_flags: DIFlags, ) -> &'ll DIType { - debug_assert_eq!(variant_layout.ty, enum_type_and_layout.ty); + assert_eq!(variant_layout.ty, enum_type_and_layout.ty); type_map::build_type_with_children( cx, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 115d5187eafa..63a9ce2fdf9c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -65,7 +65,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()); - debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout)); type_map::build_type_with_children( cx, @@ -142,7 +142,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, coroutine_def_id); let coroutine_type_and_layout = cx.layout_of(coroutine_type); - debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); + assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout)); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index e521d5e259ca..17931911f872 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -36,7 +36,7 @@ mod private { /// A unique identifier for anything that we create a debuginfo node for. /// The types it contains are expected to already be normalized (which -/// is debug_asserted in the constructors). +/// is asserted in the constructors). /// /// Note that there are some things that only show up in debuginfo, like /// the separate type descriptions for each enum variant. These get an ID @@ -58,12 +58,12 @@ pub(super) enum UniqueTypeId<'tcx> { impl<'tcx> UniqueTypeId<'tcx> { pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self { - debug_assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); + assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)); UniqueTypeId::Ty(t, private::HiddenZst) } pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self { - debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); UniqueTypeId::VariantPart(enum_ty, private::HiddenZst) } @@ -72,7 +72,7 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst) } @@ -81,7 +81,7 @@ impl<'tcx> UniqueTypeId<'tcx> { enum_ty: Ty<'tcx>, variant_idx: VariantIdx, ) -> Self { - debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); + assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)); UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst) } @@ -90,11 +90,8 @@ impl<'tcx> UniqueTypeId<'tcx> { self_type: Ty<'tcx>, implemented_trait: Option>, ) -> Self { - debug_assert_eq!( - self_type, - tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type) - ); - debug_assert_eq!( + assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)); + assert_eq!( implemented_trait, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait) ); @@ -252,10 +249,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>, generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<&'ll DIType>, ) -> DINodeCreationResult<'ll> { - debug_assert_eq!( - debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), - None - ); + assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None); debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index 155e7a89fd8b..9bd2ccceadf3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -81,7 +81,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>( ty::Dynamic(..) => Some(FatPtrKind::Dyn), ty::Foreign(_) => { // Assert that pointers to foreign types really are thin: - debug_assert_eq!( + assert_eq!( cx.size_of(Ty::new_imm_ptr(cx.tcx, pointee_tail_ty)), cx.size_of(Ty::new_imm_ptr(cx.tcx, cx.tcx.types.u8)) ); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 6abe4fa1c380..b7ad09b055a9 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -352,7 +352,7 @@ fn exported_symbols_provider_local( } MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => { // A little sanity-check - debug_assert_eq!( + assert_eq!( args.non_erasable_generics(tcx, def_id).next(), Some(GenericArgKind::Type(ty)) ); @@ -370,7 +370,7 @@ fn exported_symbols_provider_local( args, }) => { // A little sanity-check - debug_assert_eq!( + assert_eq!( args.non_erasable_generics(tcx, def_id).next(), Some(GenericArgKind::Type(ty)) ); @@ -462,7 +462,7 @@ fn upstream_monomorphizations_for_provider( tcx: TyCtxt<'_>, def_id: DefId, ) -> Option<&UnordMap, CrateNum>> { - debug_assert!(!def_id.is_local()); + assert!(!def_id.is_local()); tcx.upstream_monomorphizations(()).get(&def_id) } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 0e48eee3dd57..56e94529bc11 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1512,7 +1512,7 @@ fn start_executing_work( // We reduce the `running` counter by one. The // `tokens.truncate()` below will take care of // giving the Token back. - debug_assert!(running_with_own_token > 0); + assert!(running_with_own_token > 0); running_with_own_token -= 1; main_thread_state = MainThreadState::Lending; } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index c4e5c8582404..6a6d47fcbba3 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -459,7 +459,7 @@ fn push_debuginfo_type_name<'tcx>( output: &mut String, visited: &mut FxHashSet>, ) { - debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout)); + assert!(!wants_c_like_enum_debuginfo(ty_and_layout)); output.push_str("enum2$<"); push_inner(output, visited); push_close_angle_bracket(true, output); @@ -660,7 +660,7 @@ fn push_generic_params_internal<'tcx>( output: &mut String, visited: &mut FxHashSet>, ) -> bool { - debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); + assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args)); let mut args = args.non_erasable_generics(tcx, def_id).peekable(); if args.peek().is_none() { return false; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6a5525dc2b34..3facbabb2386 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } if is_cleanupret { // Cross-funclet jump - need a trampoline - debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess)); + assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess)); debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target); let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name); diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 6b89636b6540..82ed5610d9ea 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -194,7 +194,7 @@ fn calculate_debuginfo_offset< } _ => { // Sanity check for `can_use_in_debuginfo`. - debug_assert!(!elem.can_use_in_debuginfo()); + assert!(!elem.can_use_in_debuginfo()); bug!("unsupported var debuginfo projection `{:?}`", projection) } } @@ -502,7 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } = calculate_debuginfo_offset(bx, &fragment.projection, var_layout); - debug_assert!(indirect_offsets.is_empty()); + assert!(indirect_offsets.is_empty()); if fragment_layout.size == Size::ZERO { // Fragment is a ZST, so does not represent anything. Avoid generating anything diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index cc0e91396506..e08d7a3e8265 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -565,7 +565,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { for elem in place_ref.projection.iter() { match elem { mir::ProjectionElem::Field(ref f, _) => { - debug_assert!( + assert!( !o.layout.ty.is_any_ptr(), "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \ but tried to access field {f:?} of pointer {o:?}", diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 97d5bb831289..4394ffb7a1cf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -55,7 +55,7 @@ impl PlaceValue { /// Creates a `PlaceRef` to this location with the given type. pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> { - debug_assert!( + assert!( layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(), "Had pointer metadata {:?} for sized type {layout:?}", self.llextra, @@ -488,7 +488,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_base = match *elem { mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()), mir::ProjectionElem::Field(ref field, _) => { - debug_assert!( + assert!( !cg_base.layout.ty.is_any_ptr(), "Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \ but tried to access field {field:?} of pointer {cg_base:?}", diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f9e928a84a78..0cd3e60b0ccb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -168,8 +168,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dst: PlaceRef<'tcx, Bx::Value>, ) { // The MIR validator enforces no unsized transmutes. - debug_assert!(src.layout.is_sized()); - debug_assert!(dst.layout.is_sized()); + assert!(src.layout.is_sized()); + assert!(dst.layout.is_sized()); if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) { val.store(bx, dst); @@ -223,8 +223,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match operand.val { OperandValue::Ref(source_place_val) => { - debug_assert_eq!(source_place_val.llextra, None); - debug_assert!(matches!(operand_kind, OperandValueKind::Ref)); + assert_eq!(source_place_val.llextra, None); + assert!(matches!(operand_kind, OperandValueKind::Ref)); Some(bx.load_operand(source_place_val.with_type(cast)).val) } OperandValue::ZeroSized => { @@ -295,7 +295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { to_scalar: abi::Scalar, to_backend_ty: Bx::Type, ) -> Bx::Value { - debug_assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx)); + assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx)); use abi::Primitive::*; imm = bx.from_immediate(imm); @@ -639,9 +639,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (OperandValue::Immediate(llval), operand.layout) } mir::UnOp::PtrMetadata => { - debug_assert!( - operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(), - ); + assert!(operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),); let (_, meta) = operand.val.pointer_parts(); assert_eq!(operand.layout.fields.count() > 1, meta.is_some()); if let Some(meta) = meta { @@ -651,7 +649,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } }; - debug_assert!( + assert!( val.is_expected_variant_for_type(self.cx, layout), "Made wrong variant {val:?} for type {layout:?}", ); @@ -742,7 +740,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("Field {field_idx:?} is {p:?} making {layout:?}"); }); let scalars = self.value_kind(op.layout).scalars().unwrap(); - debug_assert_eq!(values.len(), scalars.len()); + assert_eq!(values.len(), scalars.len()); inputs.extend(values); input_scalars.extend(scalars); } @@ -760,7 +758,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); let val = OperandValue::from_immediates(inputs); - debug_assert!( + assert!( val.is_expected_variant_for_type(self.cx, layout), "Made wrong variant {val:?} for type {layout:?}", ); @@ -805,7 +803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = cg_place.val.address(); let ty = cg_place.layout.ty; - debug_assert!( + assert!( if bx.cx().type_has_metadata(ty) { matches!(val, OperandValue::Pair(..)) } else { @@ -927,7 +925,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::BinOp::Cmp => { use std::cmp::Ordering; - debug_assert!(!is_float); + assert!(!is_float); let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed); if bx.cx().tcx().sess.opts.optimize == OptLevel::No { // FIXME: This actually generates tighter assembly, and is a classic trick @@ -1111,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if layout.is_zst() { OperandValueKind::ZeroSized } else if self.cx.is_backend_immediate(layout) { - debug_assert!(!self.cx.is_backend_scalar_pair(layout)); + assert!(!self.cx.is_backend_scalar_pair(layout)); OperandValueKind::Immediate(match layout.abi { abi::Abi::Scalar(s) => s, abi::Abi::Vector { element, .. } => element, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 2f0daefa46a6..42980d9ebd24 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -165,7 +165,7 @@ pub trait BuilderMethods<'a, 'tcx>: size: Size, ) -> Self::Value; fn load_from_place(&mut self, ty: Self::Type, place: PlaceValue) -> Self::Value { - debug_assert_eq!(place.llextra, None); + assert_eq!(place.llextra, None); self.load(ty, place.llval, place.align) } fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>) @@ -184,7 +184,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value; fn store_to_place(&mut self, val: Self::Value, place: PlaceValue) -> Self::Value { - debug_assert_eq!(place.llextra, None); + assert_eq!(place.llextra, None); self.store(val, place.llval, place.align) } fn store_with_flags( @@ -200,7 +200,7 @@ pub trait BuilderMethods<'a, 'tcx>: place: PlaceValue, flags: MemFlags, ) -> Self::Value { - debug_assert_eq!(place.llextra, None); + assert_eq!(place.llextra, None); self.store_with_flags(val, place.llval, place.align, flags) } fn atomic_store( @@ -320,9 +320,9 @@ pub trait BuilderMethods<'a, 'tcx>: layout: TyAndLayout<'tcx>, flags: MemFlags, ) { - debug_assert!(layout.is_sized(), "cannot typed-copy an unsigned type"); - debug_assert!(src.llextra.is_none(), "cannot directly copy from unsized values"); - debug_assert!(dst.llextra.is_none(), "cannot directly copy into unsized values"); + assert!(layout.is_sized(), "cannot typed-copy an unsigned type"); + assert!(src.llextra.is_none(), "cannot directly copy from unsized values"); + assert!(dst.llextra.is_none(), "cannot directly copy into unsized values"); if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let ty = self.backend_type(layout); From ef07fe1b2811836ee4b5b30e94c74061bc66d06c Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 17 Jul 2024 11:40:02 -0400 Subject: [PATCH 24/49] rewrite pointer-auth-link-with-c to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../pointer-auth-link-with-c/Makefile | 15 ---------- .../pointer-auth-link-with-c/rmake.rs | 28 +++++++++++++++++++ 3 files changed, 28 insertions(+), 16 deletions(-) delete mode 100644 tests/run-make/pointer-auth-link-with-c/Makefile create mode 100644 tests/run-make/pointer-auth-link-with-c/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 6b3533c25785..57e52551deee 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -60,7 +60,6 @@ run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-gen-no-imp-symbols/Makefile run-make/pgo-indirect-call-promotion/Makefile -run-make/pointer-auth-link-with-c/Makefile run-make/print-calling-conventions/Makefile run-make/print-target-list/Makefile run-make/raw-dylib-alt-calling-convention/Makefile diff --git a/tests/run-make/pointer-auth-link-with-c/Makefile b/tests/run-make/pointer-auth-link-with-c/Makefile deleted file mode 100644 index 8fcf10e2096c..000000000000 --- a/tests/run-make/pointer-auth-link-with-c/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -include ../tools.mk - -# only-aarch64 -# ignore-cross-compile - -all: - $(COMPILE_OBJ) $(TMPDIR)/test.o test.c - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) --target $(TARGET) -Z branch-protection=bti,pac-ret,leaf test.rs - $(call RUN,test) - - $(COMPILE_OBJ) $(TMPDIR)/test.o test.c -mbranch-protection=bti+pac-ret+leaf - $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o - $(RUSTC) --target $(TARGET) -Z branch-protection=bti,pac-ret,leaf test.rs - $(call RUN,test) diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs new file mode 100644 index 000000000000..960eafa546b8 --- /dev/null +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -0,0 +1,28 @@ +// `-Z branch protection` is an unstable compiler feature which adds pointer-authentication +// code (PAC), a useful hashing measure for verifying that pointers have not been modified. +// This test checks that compilation and execution is successful when this feature is activated, +// with some of its possible extra arguments (bti, pac-ret, leaf). +// See https://github.com/rust-lang/rust/pull/88354 + +//@ only-aarch64 +// Reason: branch protection is not supported on other architectures +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib, cc, is_msvc, llvm_ar, run, rustc}; + +fn main() { + build_native_static_lib("test"); + rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run(); + run("test"); + cc().arg("-v") + .arg("-c") + .out_exe("test") + .input("test.c") + .arg("-mbranch-protection=bti+pac-ret+leaf") + .run(); + let obj_file = if is_msvc() { "test.obj" } else { "test" }; + llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); + rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run(); + run("test"); +} From 63286d80a1822df32c2f18fb7968a1368d8da8d6 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 17 Jul 2024 12:07:28 -0400 Subject: [PATCH 25/49] rewrite c-dynamic-rlib to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/c-dynamic-rlib/Makefile | 19 ---------------- tests/run-make/c-dynamic-rlib/rmake.rs | 22 +++++++++++++++++++ 3 files changed, 22 insertions(+), 20 deletions(-) delete mode 100644 tests/run-make/c-dynamic-rlib/Makefile create mode 100644 tests/run-make/c-dynamic-rlib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 57e52551deee..b85e5dfe3edc 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,6 +1,5 @@ run-make/branch-protection-check-IBT/Makefile run-make/c-dynamic-dylib/Makefile -run-make/c-dynamic-rlib/Makefile run-make/c-unwind-abi-catch-lib-panic/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile diff --git a/tests/run-make/c-dynamic-rlib/Makefile b/tests/run-make/c-dynamic-rlib/Makefile deleted file mode 100644 index 7b05e3d91a09..000000000000 --- a/tests/run-make/c-dynamic-rlib/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# This test checks that dynamic Rust linking with C does not encounter any errors, with static dependencies given preference over dynamic. (This is the default behaviour.) -# See https://github.com/rust-lang/rust/issues/10434 - -# ignore-cross-compile -include ../tools.mk - -# ignore-apple -# -# This hits an assertion in the linker on older versions of osx apparently - -# This overrides the LD_LIBRARY_PATH for RUN -TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR) - -all: $(call DYLIB,cfoo) - $(RUSTC) foo.rs - $(RUSTC) bar.rs - $(call RUN,bar) - $(call REMOVE_DYLIBS,cfoo) - $(call FAIL,bar) diff --git a/tests/run-make/c-dynamic-rlib/rmake.rs b/tests/run-make/c-dynamic-rlib/rmake.rs new file mode 100644 index 000000000000..c48b1edee9e6 --- /dev/null +++ b/tests/run-make/c-dynamic-rlib/rmake.rs @@ -0,0 +1,22 @@ +// This test checks that dynamic Rust linking with C does not encounter any errors in both +// compilation and execution, with static dependencies given preference over dynamic. +// (This is the default behaviour.) +// See https://github.com/rust-lang/rust/issues/10434 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +//FIXME(Oneirical): test on apple because older versions of osx are failing apparently + +use run_make_support::{ + build_native_dynamic_lib, dynamic_lib_name, fs_wrapper, run, run_fail, rustc, +}; + +fn main() { + build_native_dynamic_lib("cfoo"); + rustc().input("foo.rs").run(); + rustc().input("bar.rs").run(); + run("bar"); + fs_wrapper::remove_file(dynamic_lib_name("cfoo")); + run_fail("bar"); +} From 710e7b0c7581efcbb2d913738d1ec17f0a726387 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 17 Jul 2024 15:11:09 -0400 Subject: [PATCH 26/49] rewrite c-dynamic-dylib to rmake --- .../src/external_deps/c_build.rs | 37 ++++++++++++++++++- src/tools/run-make-support/src/fs.rs | 15 +++++++- src/tools/run-make-support/src/lib.rs | 2 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/c-dynamic-dylib/Makefile | 16 -------- tests/run-make/c-dynamic-dylib/rmake.rs | 17 +++++++++ tests/run-make/c-dynamic-rlib/rmake.rs | 8 +--- 7 files changed, 69 insertions(+), 27 deletions(-) delete mode 100644 tests/run-make/c-dynamic-dylib/Makefile create mode 100644 tests/run-make/c-dynamic-dylib/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 35b2bf75c95f..86c9c0818319 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,10 +1,13 @@ use std::path::PathBuf; -use crate::artifact_names::static_lib_name; +use super::cygpath::get_windows_path; +use crate::artifact_names::{dynamic_lib_name, static_lib_name}; use crate::external_deps::cc::cc; use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; -use crate::targets::is_msvc; +use crate::targets::{is_darwin, is_msvc, is_windows}; + +// FIXME(Oneirical): These native build functions should take a Path-based generic. /// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. #[track_caller] @@ -25,3 +28,33 @@ pub fn build_native_static_lib(lib_name: &str) -> PathBuf { llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run(); path(lib_path) } + +/// Builds a dynamic lib. The filename is computed in a target-dependent manner, relying on +/// [`std::env::consts::DLL_PREFIX`] and [`std::env::consts::DLL_EXTENSION`]. +#[track_caller] +pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf { + let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; + let src = format!("{lib_name}.c"); + let lib_path = dynamic_lib_name(lib_name); + if is_msvc() { + cc().arg("-c").out_exe(&obj_file).input(src).run(); + } else { + cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run(); + }; + let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") }; + if is_msvc() { + let mut out_arg = "-out:".to_owned(); + out_arg.push_str(&get_windows_path(&lib_path)); + cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run(); + } else if is_darwin() { + cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run(); + } else if is_windows() { + cc().out_exe(&lib_path) + .input(&obj_file) + .args(&["-shared", &format!("-Wl,--out-implib={lib_path}.a")]) + .run(); + } else { + cc().out_exe(&lib_path).input(&obj_file).arg("-shared").run(); + } + path(lib_path) +} diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index f346e983aea8..0a7961616330 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -1,5 +1,5 @@ use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; // FIXME(jieyouxu): modify create_symlink to panic on windows. @@ -176,3 +176,16 @@ pub fn set_permissions>(path: P, perm: std::fs::Permissions) { path.as_ref().display() )); } + +/// A function which prints all file names in the directory `dir` similarly to Unix's `ls`. +/// Useful for debugging. +/// Usage: `eprintln!("{:#?}", shallow_find_dir_entries(some_dir));` +#[track_caller] +pub fn shallow_find_dir_entries>(dir: P) -> Vec { + let paths = read_dir(dir); + let mut output = Vec::new(); + for path in paths { + output.push(path.unwrap().path()); + } + output +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index b85191970de6..a4bb9056346d 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -43,7 +43,7 @@ pub use wasmparser; pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc}; // These rely on external dependencies. -pub use c_build::build_native_static_lib; +pub use c_build::{build_native_dynamic_lib, build_native_static_lib}; pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index b85e5dfe3edc..88010f939061 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,5 +1,4 @@ run-make/branch-protection-check-IBT/Makefile -run-make/c-dynamic-dylib/Makefile run-make/c-unwind-abi-catch-lib-panic/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile diff --git a/tests/run-make/c-dynamic-dylib/Makefile b/tests/run-make/c-dynamic-dylib/Makefile deleted file mode 100644 index 39561b28222c..000000000000 --- a/tests/run-make/c-dynamic-dylib/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# This test checks that dynamic Rust linking with C does not encounter any errors, with dynamic dependencies given preference over static. -# See https://github.com/rust-lang/rust/issues/10434 - -# ignore-cross-compile -include ../tools.mk - -# ignore-apple -# -# This hits an assertion in the linker on older versions of osx apparently - -all: $(call DYLIB,cfoo) - $(RUSTC) foo.rs -C prefer-dynamic - $(RUSTC) bar.rs - $(call RUN,bar) - $(call REMOVE_DYLIBS,cfoo) - $(call FAIL,bar) diff --git a/tests/run-make/c-dynamic-dylib/rmake.rs b/tests/run-make/c-dynamic-dylib/rmake.rs new file mode 100644 index 000000000000..65b5e02abf08 --- /dev/null +++ b/tests/run-make/c-dynamic-dylib/rmake.rs @@ -0,0 +1,17 @@ +// This test checks that dynamic Rust linking with C does not encounter any errors in both +// compilation and execution, with dynamic dependencies given preference over static. +// See https://github.com/rust-lang/rust/issues/10434 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_dynamic_lib, dynamic_lib_name, rfs, run, run_fail, rustc}; + +fn main() { + build_native_dynamic_lib("cfoo"); + rustc().input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().input("bar.rs").run(); + run("bar"); + rfs::remove_file(dynamic_lib_name("cfoo")); + run_fail("bar"); +} diff --git a/tests/run-make/c-dynamic-rlib/rmake.rs b/tests/run-make/c-dynamic-rlib/rmake.rs index c48b1edee9e6..b59887bbdd63 100644 --- a/tests/run-make/c-dynamic-rlib/rmake.rs +++ b/tests/run-make/c-dynamic-rlib/rmake.rs @@ -6,17 +6,13 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -//FIXME(Oneirical): test on apple because older versions of osx are failing apparently - -use run_make_support::{ - build_native_dynamic_lib, dynamic_lib_name, fs_wrapper, run, run_fail, rustc, -}; +use run_make_support::{build_native_dynamic_lib, dynamic_lib_name, rfs, run, run_fail, rustc}; fn main() { build_native_dynamic_lib("cfoo"); rustc().input("foo.rs").run(); rustc().input("bar.rs").run(); run("bar"); - fs_wrapper::remove_file(dynamic_lib_name("cfoo")); + rfs::remove_file(dynamic_lib_name("cfoo")); run_fail("bar"); } From da692ee0eaa2ab4498ab86d6ad984c6c8bf327a1 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 23 Jul 2024 11:24:05 -0400 Subject: [PATCH 27/49] rewrite extern-diff-internal-name to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/extern-diff-internal-name/Makefile | 6 ------ .../run-make/extern-diff-internal-name/rmake.rs | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) delete mode 100644 tests/run-make/extern-diff-internal-name/Makefile create mode 100644 tests/run-make/extern-diff-internal-name/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 158d5cc8aded..09ee4d0707ba 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -15,7 +15,6 @@ run-make/dep-info/Makefile run-make/dump-ice-to-disk/Makefile run-make/emit-to-stdout/Makefile run-make/export-executable-symbols/Makefile -run-make/extern-diff-internal-name/Makefile run-make/extern-flag-disambiguates/Makefile run-make/extern-fn-reachable/Makefile run-make/extern-multiple-copies/Makefile diff --git a/tests/run-make/extern-diff-internal-name/Makefile b/tests/run-make/extern-diff-internal-name/Makefile deleted file mode 100644 index 250f82dfac08..000000000000 --- a/tests/run-make/extern-diff-internal-name/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) lib.rs - $(RUSTC) test.rs --extern foo=$(TMPDIR)/libbar.rlib diff --git a/tests/run-make/extern-diff-internal-name/rmake.rs b/tests/run-make/extern-diff-internal-name/rmake.rs new file mode 100644 index 000000000000..13aec894472e --- /dev/null +++ b/tests/run-make/extern-diff-internal-name/rmake.rs @@ -0,0 +1,17 @@ +// In the following scenario: +// 1. The crate foo, is referenced multiple times +// 2. --extern foo=./path/to/libbar.rlib is specified to rustc +// 3. The internal crate name of libbar.rlib is not foo +// Compilation fails with the "multiple crate versions" error message. +// As this was fixed in #17189, this regression test ensures this bug does not +// make a resurgence. +// See https://github.com/rust-lang/rust/pull/17189 + +//FIXME(Oneirical): test-various + +use run_make_support::{rust_lib_name, rustc}; + +fn main() { + rustc().input("lib.rs").run(); + rustc().input("test.rs").extern_("foo", rust_lib_name("bar")).run(); +} From 4332f5d81afa778e7a80e670fc8116474e36ecaa Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 23 Jul 2024 11:54:10 -0400 Subject: [PATCH 28/49] rewrite extern-multiple-copies to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/extern-multiple-copies/Makefile | 9 --------- tests/run-make/extern-multiple-copies/rmake.rs | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/extern-multiple-copies/Makefile create mode 100644 tests/run-make/extern-multiple-copies/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 09ee4d0707ba..5df5f844b265 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -17,7 +17,6 @@ run-make/emit-to-stdout/Makefile run-make/export-executable-symbols/Makefile run-make/extern-flag-disambiguates/Makefile run-make/extern-fn-reachable/Makefile -run-make/extern-multiple-copies/Makefile run-make/extern-multiple-copies2/Makefile run-make/fmt-write-bloat/Makefile run-make/foreign-double-unwind/Makefile diff --git a/tests/run-make/extern-multiple-copies/Makefile b/tests/run-make/extern-multiple-copies/Makefile deleted file mode 100644 index b0b84278edac..000000000000 --- a/tests/run-make/extern-multiple-copies/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo1.rs - $(RUSTC) foo2.rs - mkdir $(TMPDIR)/foo - cp $(TMPDIR)/libfoo1.rlib $(TMPDIR)/foo/libfoo1.rlib - $(RUSTC) bar.rs --extern foo1=$(TMPDIR)/libfoo1.rlib -L $(TMPDIR)/foo diff --git a/tests/run-make/extern-multiple-copies/rmake.rs b/tests/run-make/extern-multiple-copies/rmake.rs new file mode 100644 index 000000000000..94dd26af5e6e --- /dev/null +++ b/tests/run-make/extern-multiple-copies/rmake.rs @@ -0,0 +1,17 @@ +// In this test, the rust library foo1 exists in two different locations, but only one +// is required by the --extern flag. This test checks that the copy is ignored (as --extern +// demands fetching only the original instance of foo1) and that no error is emitted, resulting +// in successful compilation. +// https://github.com/rust-lang/rust/pull/29961 + +// FIXME(Oneirical): test-various + +use run_make_support::{path, rfs, rust_lib_name, rustc}; + +fn main() { + rustc().input("foo1.rs").run(); + rustc().input("foo2.rs").run(); + rfs::create_dir("foo"); + rfs::copy(rust_lib_name("foo1"), path("foo").join(rust_lib_name("foo1"))); + rustc().input("bar.rs").extern_("foo1", rust_lib_name("foo1")).library_search_path("foo").run(); +} From 421619da488f2575b8889a5f173a9e81e0fc5826 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 23 Jul 2024 12:00:46 -0400 Subject: [PATCH 29/49] rewrite extern-multiple-copies2 to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../extern-diff-internal-name/rmake.rs | 2 -- .../run-make/extern-multiple-copies/rmake.rs | 2 -- .../run-make/extern-multiple-copies2/Makefile | 11 ---------- .../run-make/extern-multiple-copies2/rmake.rs | 22 +++++++++++++++++++ 5 files changed, 22 insertions(+), 16 deletions(-) delete mode 100644 tests/run-make/extern-multiple-copies2/Makefile create mode 100644 tests/run-make/extern-multiple-copies2/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5df5f844b265..65ec470c1707 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -17,7 +17,6 @@ run-make/emit-to-stdout/Makefile run-make/export-executable-symbols/Makefile run-make/extern-flag-disambiguates/Makefile run-make/extern-fn-reachable/Makefile -run-make/extern-multiple-copies2/Makefile run-make/fmt-write-bloat/Makefile run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile diff --git a/tests/run-make/extern-diff-internal-name/rmake.rs b/tests/run-make/extern-diff-internal-name/rmake.rs index 13aec894472e..1a7f34d65bc2 100644 --- a/tests/run-make/extern-diff-internal-name/rmake.rs +++ b/tests/run-make/extern-diff-internal-name/rmake.rs @@ -7,8 +7,6 @@ // make a resurgence. // See https://github.com/rust-lang/rust/pull/17189 -//FIXME(Oneirical): test-various - use run_make_support::{rust_lib_name, rustc}; fn main() { diff --git a/tests/run-make/extern-multiple-copies/rmake.rs b/tests/run-make/extern-multiple-copies/rmake.rs index 94dd26af5e6e..8b67e6d9facf 100644 --- a/tests/run-make/extern-multiple-copies/rmake.rs +++ b/tests/run-make/extern-multiple-copies/rmake.rs @@ -4,8 +4,6 @@ // in successful compilation. // https://github.com/rust-lang/rust/pull/29961 -// FIXME(Oneirical): test-various - use run_make_support::{path, rfs, rust_lib_name, rustc}; fn main() { diff --git a/tests/run-make/extern-multiple-copies2/Makefile b/tests/run-make/extern-multiple-copies2/Makefile deleted file mode 100644 index 708b1c1b5409..000000000000 --- a/tests/run-make/extern-multiple-copies2/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo1.rs - $(RUSTC) foo2.rs - mkdir $(TMPDIR)/foo - cp $(TMPDIR)/libfoo1.rlib $(TMPDIR)/foo/libfoo1.rlib - $(RUSTC) bar.rs \ - --extern foo1=$(TMPDIR)/foo/libfoo1.rlib \ - --extern foo2=$(TMPDIR)/libfoo2.rlib diff --git a/tests/run-make/extern-multiple-copies2/rmake.rs b/tests/run-make/extern-multiple-copies2/rmake.rs new file mode 100644 index 000000000000..59913bfa42bb --- /dev/null +++ b/tests/run-make/extern-multiple-copies2/rmake.rs @@ -0,0 +1,22 @@ +// Almost identical to `extern-multiple-copies`, but with a variation in the --extern calls +// and the addition of #[macro_use] in the rust code files, which used to break --extern +// until #33625. +// In this test, the rust library foo1 exists in two different locations, but only one +// is required by the --extern flag. This test checks that the copy is ignored (as --extern +// demands fetching only the original instance of foo1) and that no error is emitted, resulting +// in successful compilation. +// https://github.com/rust-lang/rust/issues/33762 + +use run_make_support::{path, rfs, rust_lib_name, rustc}; + +fn main() { + rustc().input("foo1.rs").run(); + rustc().input("foo2.rs").run(); + rfs::create_dir("foo"); + rfs::copy(rust_lib_name("foo1"), path("foo").join(rust_lib_name("foo1"))); + rustc() + .input("bar.rs") + .extern_("foo1", path("foo").join(rust_lib_name("foo1"))) + .extern_("foo2", rust_lib_name("foo2")) + .run(); +} From c31ff97bf1f9fbbd37a501cef0b019faa43b0b7f Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 24 Jul 2024 15:04:43 +0200 Subject: [PATCH 30/49] centralize turning asm flags into human readable names --- compiler/rustc_ast/src/ast.rs | 36 +++++++++++++++++++ compiler/rustc_ast_pretty/src/pprust/state.rs | 30 +--------------- compiler/rustc_hir_pretty/src/lib.rs | 30 +--------------- 3 files changed, 38 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 75c656973f96..411fc8311a08 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2264,6 +2264,42 @@ bitflags::bitflags! { } } +impl InlineAsmOptions { + pub fn human_readable_names(&self) -> Vec<&'static str> { + let mut options = vec![]; + + if self.contains(InlineAsmOptions::PURE) { + options.push("pure"); + } + if self.contains(InlineAsmOptions::NOMEM) { + options.push("nomem"); + } + if self.contains(InlineAsmOptions::READONLY) { + options.push("readonly"); + } + if self.contains(InlineAsmOptions::PRESERVES_FLAGS) { + options.push("preserves_flags"); + } + if self.contains(InlineAsmOptions::NORETURN) { + options.push("noreturn"); + } + if self.contains(InlineAsmOptions::NOSTACK) { + options.push("nostack"); + } + if self.contains(InlineAsmOptions::ATT_SYNTAX) { + options.push("att_syntax"); + } + if self.contains(InlineAsmOptions::RAW) { + options.push("raw"); + } + if self.contains(InlineAsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } + + options + } +} + impl std::fmt::Debug for InlineAsmOptions { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { bitflags::parser::to_writer(self, f) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 0568d368d8c4..b463d1f36ce5 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1505,35 +1505,7 @@ impl<'a> State<'a> { AsmArg::Options(opts) => { s.word("options"); s.popen(); - let mut options = vec![]; - if opts.contains(InlineAsmOptions::PURE) { - options.push("pure"); - } - if opts.contains(InlineAsmOptions::NOMEM) { - options.push("nomem"); - } - if opts.contains(InlineAsmOptions::READONLY) { - options.push("readonly"); - } - if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) { - options.push("preserves_flags"); - } - if opts.contains(InlineAsmOptions::NORETURN) { - options.push("noreturn"); - } - if opts.contains(InlineAsmOptions::NOSTACK) { - options.push("nostack"); - } - if opts.contains(InlineAsmOptions::ATT_SYNTAX) { - options.push("att_syntax"); - } - if opts.contains(InlineAsmOptions::RAW) { - options.push("raw"); - } - if opts.contains(InlineAsmOptions::MAY_UNWIND) { - options.push("may_unwind"); - } - s.commasep(Inconsistent, &options, |s, &opt| { + s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| { s.word(opt); }); s.pclose(); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5105d60ae188..433be3260476 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1289,35 +1289,7 @@ impl<'a> State<'a> { AsmArg::Options(opts) => { s.word("options"); s.popen(); - let mut options = vec![]; - if opts.contains(ast::InlineAsmOptions::PURE) { - options.push("pure"); - } - if opts.contains(ast::InlineAsmOptions::NOMEM) { - options.push("nomem"); - } - if opts.contains(ast::InlineAsmOptions::READONLY) { - options.push("readonly"); - } - if opts.contains(ast::InlineAsmOptions::PRESERVES_FLAGS) { - options.push("preserves_flags"); - } - if opts.contains(ast::InlineAsmOptions::NORETURN) { - options.push("noreturn"); - } - if opts.contains(ast::InlineAsmOptions::NOSTACK) { - options.push("nostack"); - } - if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) { - options.push("att_syntax"); - } - if opts.contains(ast::InlineAsmOptions::RAW) { - options.push("raw"); - } - if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) { - options.push("may_unwind"); - } - s.commasep(Inconsistent, &options, |s, &opt| { + s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| { s.word(opt); }); s.pclose(); From 4b7a87de1094522c5c6e5a7bda04e0e0b281e049 Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 24 Jul 2024 15:27:56 +0200 Subject: [PATCH 31/49] use an allow list for allowed asm options in naked functions --- compiler/rustc_passes/src/naked_functions.rs | 21 +++++++++----------- tests/ui/asm/naked-functions.rs | 2 +- tests/ui/asm/naked-functions.stderr | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index d45ee32a624d..dbbf802c920d 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -244,22 +244,19 @@ impl<'tcx> CheckInlineAssembly<'tcx> { self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands }); } - let unsupported_options: Vec<&'static str> = [ - (InlineAsmOptions::MAY_UNWIND, "`may_unwind`"), - (InlineAsmOptions::NOMEM, "`nomem`"), - (InlineAsmOptions::NOSTACK, "`nostack`"), - (InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"), - (InlineAsmOptions::PURE, "`pure`"), - (InlineAsmOptions::READONLY, "`readonly`"), - ] - .iter() - .filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None }) - .collect(); + let supported_options = + InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX; + let unsupported_options = asm.options.difference(supported_options); if !unsupported_options.is_empty() { self.tcx.dcx().emit_err(NakedFunctionsAsmOptions { span, - unsupported_options: unsupported_options.join(", "), + unsupported_options: unsupported_options + .human_readable_names() + .into_iter() + .map(|name| format!("`{name}`")) + .collect::>() + .join(", "), }); } diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 1619ebfcf39f..6b2d2aea238d 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -111,7 +111,7 @@ unsafe extern "C" fn invalid_options() { unsafe extern "C" fn invalid_options_continued() { asm!("", options(readonly, nostack), options(pure)); //~^ ERROR asm with the `pure` option must have at least one output - //~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly` + //~| ERROR asm options unsupported in naked functions: `pure`, `readonly`, `nostack` //~| ERROR asm in naked functions must use `noreturn` option } diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 77bc80a101f0..4dd9e29bdc6f 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -212,7 +212,7 @@ error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_fl LL | asm!("", options(nomem, preserves_flags, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` +error[E0787]: asm options unsupported in naked functions: `pure`, `readonly`, `nostack` --> $DIR/naked-functions.rs:112:5 | LL | asm!("", options(readonly, nostack), options(pure)); From db8cdc5d37da5c0cf306fba51d07d6af10d69bd7 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Mon, 24 Jun 2024 16:17:59 +0100 Subject: [PATCH 32/49] Use Cow<'static, str> for InlineAsmTemplatePiece::String --- compiler/rustc_ast/src/ast.rs | 3 +- compiler/rustc_builtin_macros/src/asm.rs | 6 +-- .../rustc_codegen_cranelift/src/inline_asm.rs | 4 +- .../src/intrinsics/llvm_x86.rs | 42 ++++++++++--------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 75c656973f96..4d19be62df80 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -36,6 +36,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use std::borrow::Cow; use std::cmp; use std::fmt; use std::mem; @@ -2272,7 +2273,7 @@ impl std::fmt::Debug for InlineAsmOptions { #[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)] pub enum InlineAsmTemplatePiece { - String(String), + String(Cow<'static, str>), Placeholder { operand_idx: usize, modifier: Option, span: Span }, } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index dd0f9aaf2210..b8fe6338493d 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -459,7 +459,7 @@ fn expand_preparsed_asm( for (i, template_expr) in args.templates.into_iter().enumerate() { if i != 0 { - template.push(ast::InlineAsmTemplatePiece::String("\n".to_string())); + template.push(ast::InlineAsmTemplatePiece::String("\n".into())); } let msg = "asm template must be a string literal"; @@ -527,7 +527,7 @@ fn expand_preparsed_asm( // Don't treat raw asm as a format string. if args.options.contains(ast::InlineAsmOptions::RAW) { - template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string())); + template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string().into())); let template_num_lines = 1 + template_str.matches('\n').count(); line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines)); continue; @@ -577,7 +577,7 @@ fn expand_preparsed_asm( for piece in unverified_pieces { match piece { parse::Piece::String(s) => { - template.push(ast::InlineAsmTemplatePiece::String(s.to_string())) + template.push(ast::InlineAsmTemplatePiece::String(s.to_string().into())) } parse::Piece::NextArgument(arg) => { let span = arg_spans.next().unwrap_or(template_sp); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index c88230c93605..16edec47e102 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -46,9 +46,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( // Used by panic_abort on Windows, but uses a syntax which only happens to work with // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. - if template.len() == 1 - && template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) - { + if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) { fx.bcx.ins().trap(TrapCode::User(1)); return; } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index e1896138e487..a20faa2cad3a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -40,7 +40,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( shl rdx, 32 or rax, rdx " - .to_string(), + .into(), )], &[ CInlineAsmOperand::In { @@ -471,7 +471,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // into 0x80000000 for which Cranelift doesn't have a native instruction. codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))], + &[InlineAsmTemplatePiece::String("cvtps2dq xmm0, xmm0".into())], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -875,7 +875,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(asm.to_string())], + &[InlineAsmTemplatePiece::String(asm.into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), @@ -914,7 +914,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -967,7 +967,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1015,7 +1015,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1052,7 +1052,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("aeskeygenassist xmm0, xmm0, {imm8}"))], + &[InlineAsmTemplatePiece::String( + format!("aeskeygenassist xmm0, xmm0, {imm8}").into(), + )], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -1071,7 +1073,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".to_string())], + &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".into())], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -1091,7 +1093,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1117,7 +1119,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1143,7 +1145,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1169,7 +1171,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1207,7 +1209,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))], + &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1233,7 +1235,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1259,7 +1261,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1285,7 +1287,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1312,7 +1314,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1343,7 +1345,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1369,7 +1371,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1435,7 +1437,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let edx_place = res_place.place_field(fx, FieldIdx::new(1)); codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("rdtsc".to_string())], + &[InlineAsmTemplatePiece::String("rdtsc".into())], &[ CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), From 850faea030db4b260719d99be4191d7803efdb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 23 Jul 2024 19:43:46 +0000 Subject: [PATCH 33/49] Do not use question as label We don't want to have questions in the diagnostic output. Instead, we use wording that communicates uncertainty, like "might": ``` error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:2:9 | LL | use spam::*; | ^^^^ you might be missing crate `spam` | = help: consider adding `extern crate spam` to use the `spam` crate ``` --- compiler/rustc_resolve/src/diagnostics.rs | 4 +- .../ice-unresolved-import-100241.stderr | 2 +- .../unresolved-import-recovery.stderr | 4 +- tests/rustdoc-ui/issues/issue-61732.rs | 2 +- tests/rustdoc-ui/issues/issue-61732.stderr | 4 +- .../session-diagnostic/diagnostic-derive.rs | 6 +-- .../diagnostic-derive.stderr | 12 ++--- .../subdiagnostic-derive.rs | 32 ++++++------- .../subdiagnostic-derive.stderr | 32 ++++++------- .../field-attributes-vis-unresolved.stderr | 8 ++-- tests/ui/error-codes/E0432.stderr | 2 +- .../feature-gate-extern_absolute_paths.stderr | 6 +-- .../imports/import-from-missing-star-2.stderr | 2 +- .../imports/import-from-missing-star-3.stderr | 4 +- .../imports/import-from-missing-star.stderr | 2 +- tests/ui/imports/import3.stderr | 2 +- tests/ui/imports/issue-109343.stderr | 2 +- tests/ui/imports/issue-1697.rs | 6 ++- tests/ui/imports/issue-1697.stderr | 2 +- tests/ui/imports/issue-33464.stderr | 6 +-- tests/ui/imports/issue-36881.stderr | 2 +- tests/ui/imports/issue-37887.stderr | 2 +- tests/ui/imports/issue-53269.stderr | 2 +- tests/ui/imports/issue-55457.stderr | 2 +- tests/ui/imports/issue-81413.stderr | 2 +- tests/ui/imports/tool-mod-child.rs | 4 +- tests/ui/imports/tool-mod-child.stderr | 12 ++--- .../ui/imports/unresolved-imports-used.stderr | 8 ++-- .../keyword-extern-as-identifier-use.stderr | 2 +- .../ui/macros/meta-item-absolute-path.stderr | 8 ++-- tests/ui/privacy/restricted/test.rs | 2 +- tests/ui/privacy/restricted/test.stderr | 4 +- tests/ui/resolve/editions-crate-root-2015.rs | 4 +- .../resolve/editions-crate-root-2015.stderr | 8 ++-- tests/ui/resolve/extern-prelude-fail.stderr | 6 +-- tests/ui/resolve/issue-82865.rs | 2 +- tests/ui/resolve/issue-82865.stderr | 4 +- .../ui/resolve/resolve-bad-visibility.stderr | 8 ++-- .../issue-102156.stderr | 8 ++-- .../portable-intrinsics-arent-exposed.stderr | 4 +- .../ui/underscore-imports/issue-110164.stderr | 8 ++-- .../unresolved-asterisk-imports.stderr | 2 +- tests/ui/unresolved/unresolved-import.rs | 48 +++++++++++-------- tests/ui/unresolved/unresolved-import.stderr | 12 ++--- 44 files changed, 156 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bf7972e392c9..046ae5fc5933 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2012,7 +2012,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) } else if ident.name == sym::core { ( - format!("maybe a missing crate `{ident}`?"), + format!("you might be missing crate `{ident}`"), Some(( vec![(ident.span, "std".to_string())], "try using `std` instead of `core`".to_string(), @@ -2021,7 +2021,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) } else if self.tcx.sess.is_rust_2015() { ( - format!("maybe a missing crate `{ident}`?"), + format!("you might be missing crate `{ident}`"), Some(( vec![], format!( diff --git a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr index 57fbbb59c8d4..e23e0f01fabe 100644 --- a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr +++ b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `inner` --> $DIR/ice-unresolved-import-100241.rs:9:13 | LL | pub use inner::S; - | ^^^^^ maybe a missing crate `inner`? + | ^^^^^ you might be missing crate `inner` | = help: consider adding `extern crate inner` to use the `inner` crate diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr index 8315c73a639f..a74e6b739389 100644 --- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr +++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`? +error[E0433]: failed to resolve: you might be missing crate `unresolved_crate` --> $DIR/unresolved-import-recovery.rs:3:5 | LL | use unresolved_crate::module::Name; - | ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`? + | ^^^^^^^^^^^^^^^^ you might be missing crate `unresolved_crate` | = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate diff --git a/tests/rustdoc-ui/issues/issue-61732.rs b/tests/rustdoc-ui/issues/issue-61732.rs index 4bd8efeaa3b9..3969ab92c32e 100644 --- a/tests/rustdoc-ui/issues/issue-61732.rs +++ b/tests/rustdoc-ui/issues/issue-61732.rs @@ -1,4 +1,4 @@ // This previously triggered an ICE. pub(in crate::r#mod) fn main() {} -//~^ ERROR failed to resolve: maybe a missing crate `r#mod` +//~^ ERROR failed to resolve: you might be missing crate `r#mod` diff --git a/tests/rustdoc-ui/issues/issue-61732.stderr b/tests/rustdoc-ui/issues/issue-61732.stderr index f351f52d1e15..f49d53b0d9ad 100644 --- a/tests/rustdoc-ui/issues/issue-61732.stderr +++ b/tests/rustdoc-ui/issues/issue-61732.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: maybe a missing crate `r#mod`? +error[E0433]: failed to resolve: you might be missing crate `r#mod` --> $DIR/issue-61732.rs:3:15 | LL | pub(in crate::r#mod) fn main() {} - | ^^^^^ maybe a missing crate `r#mod`? + | ^^^^^ you might be missing crate `r#mod` | = help: consider adding `extern crate r#mod` to use the `r#mod` crate diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index dc268dfc5caf..e8cec6321772 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -56,7 +56,7 @@ enum DiagnosticOnEnum { #[derive(Diagnostic)] #[diag(no_crate_example, code = E0123)] #[diag = "E0123"] -//~^ ERROR failed to resolve: maybe a missing crate `core` +//~^ ERROR failed to resolve: you might be missing crate `core` struct WrongStructAttrStyle {} #[derive(Diagnostic)] @@ -801,7 +801,7 @@ struct SuggestionsNoItem { struct SuggestionsInvalidItem { #[suggestion(code(foo))] //~^ ERROR `code(...)` must contain only string literals - //~| ERROR failed to resolve: maybe a missing crate `core` + //~| ERROR failed to resolve: you might be missing crate `core` sub: Span, } @@ -809,7 +809,7 @@ struct SuggestionsInvalidItem { #[diag(no_crate_example)] struct SuggestionsInvalidLiteral { #[suggestion(code = 3)] - //~^ ERROR failed to resolve: maybe a missing crate `core` + //~^ ERROR failed to resolve: you might be missing crate `core` sub: Span, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index e36c6852d3b2..97f9896f3a72 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -524,23 +524,23 @@ LL | #[suggestion(no_crate_suggestion, code = "")] = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]` = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/diagnostic-derive.rs:58:8 | LL | #[diag = "E0123"] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/diagnostic-derive.rs:802:23 | LL | #[suggestion(code(foo))] - | ^^^ maybe a missing crate `core`? + | ^^^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/diagnostic-derive.rs:811:25 | LL | #[suggestion(code = 3)] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:63:3 diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 659ae54f7a3b..c837372a7a7a 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -94,8 +94,8 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] -//~^ ERROR failed to resolve: maybe a missing crate `core`? -//~| NOTE maybe a missing crate `core`? +//~^ ERROR failed to resolve: you might be missing crate `core` +//~| NOTE you might be missing crate `core` struct H { #[primary_span] span: Span, @@ -310,8 +310,8 @@ struct AB { #[derive(Subdiagnostic)] union AC { - //~^ ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~^ ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span: u32, b: u64, } @@ -581,8 +581,8 @@ struct BD { span2: Span, #[suggestion_part(foo = "bar")] //~^ ERROR `code` is the only valid nested attribute - //~| ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~| ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span4: Span, #[suggestion_part(code = "...")] //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` @@ -674,8 +674,8 @@ enum BL { struct BM { #[suggestion_part(code("foo"))] //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~| ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span: Span, r#type: String, } @@ -685,8 +685,8 @@ struct BM { struct BN { #[suggestion_part(code("foo", "bar"))] //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~| ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span: Span, r#type: String, } @@ -696,8 +696,8 @@ struct BN { struct BO { #[suggestion_part(code(3))] //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~| ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span: Span, r#type: String, } @@ -718,8 +718,8 @@ struct BP { #[multipart_suggestion(no_crate_example)] struct BQ { #[suggestion_part(code = 3)] - //~^ ERROR failed to resolve: maybe a missing crate `core`? - //~| NOTE maybe a missing crate `core`? + //~^ ERROR failed to resolve: you might be missing crate `core` + //~| NOTE you might be missing crate `core` span: Span, r#type: String, } @@ -811,8 +811,8 @@ struct SuggestionStyleInvalid3 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style("foo"))] //~^ ERROR expected `= "xxx"` -//~| ERROR failed to resolve: maybe a missing crate `core`? -//~| NOTE maybe a missing crate `core`? +//~| ERROR failed to resolve: you might be missing crate `core` +//~| NOTE you might be missing crate `core` struct SuggestionStyleInvalid4 { #[primary_span] sub: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index fccf3757dbec..96f6ef06d1dc 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -451,53 +451,53 @@ error: suggestion without `#[primary_span]` field LL | #[suggestion(no_crate_example, code = "")] | ^ -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:96:9 | LL | #[label("...")] - | ^^^^^ maybe a missing crate `core`? + | ^^^^^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:312:1 | LL | union AC { - | ^^^^^ maybe a missing crate `core`? + | ^^^^^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:582:27 | LL | #[suggestion_part(foo = "bar")] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:675:28 | LL | #[suggestion_part(code("foo"))] - | ^^^^^ maybe a missing crate `core`? + | ^^^^^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:686:28 | LL | #[suggestion_part(code("foo", "bar"))] - | ^^^^^ maybe a missing crate `core`? + | ^^^^^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:697:28 | LL | #[suggestion_part(code(3))] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:720:30 | LL | #[suggestion_part(code = 3)] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/subdiagnostic-derive.rs:812:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] - | ^ maybe a missing crate `core`? + | ^ you might be missing crate `core` error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:67:3 diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.stderr b/tests/ui/attributes/field-attributes-vis-unresolved.stderr index 439762546381..819cd859ae90 100644 --- a/tests/ui/attributes/field-attributes-vis-unresolved.stderr +++ b/tests/ui/attributes/field-attributes-vis-unresolved.stderr @@ -1,16 +1,16 @@ -error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? +error[E0433]: failed to resolve: you might be missing crate `nonexistent` --> $DIR/field-attributes-vis-unresolved.rs:17:12 | LL | pub(in nonexistent) field: u8 - | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | ^^^^^^^^^^^ you might be missing crate `nonexistent` | = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate -error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? +error[E0433]: failed to resolve: you might be missing crate `nonexistent` --> $DIR/field-attributes-vis-unresolved.rs:22:12 | LL | pub(in nonexistent) u8 - | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | ^^^^^^^^^^^ you might be missing crate `nonexistent` | = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr index 473e82f86343..a0b17e35c94a 100644 --- a/tests/ui/error-codes/E0432.stderr +++ b/tests/ui/error-codes/E0432.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `something` --> $DIR/E0432.rs:1:5 | LL | use something::Foo; - | ^^^^^^^^^ maybe a missing crate `something`? + | ^^^^^^^^^ you might be missing crate `something` | = help: consider adding `extern crate something` to use the `something` crate diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr index 2fcad98be9f7..0234480ac5ac 100644 --- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -4,14 +4,14 @@ error[E0432]: unresolved import `core` LL | use core::default; | ^^^^ | | - | maybe a missing crate `core`? + | you might be missing crate `core` | help: try using `std` instead of `core`: `std` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/feature-gate-extern_absolute_paths.rs:4:19 | LL | let _: u8 = ::core::default::Default(); - | ^^^^ maybe a missing crate `core`? + | ^^^^ you might be missing crate `core` | help: try using `std` instead of `core` | diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr index ea3876248c93..59b000a43822 100644 --- a/tests/ui/imports/import-from-missing-star-2.stderr +++ b/tests/ui/imports/import-from-missing-star-2.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-2.rs:2:9 | LL | use spam::*; - | ^^^^ maybe a missing crate `spam`? + | ^^^^ you might be missing crate `spam` | = help: consider adding `extern crate spam` to use the `spam` crate diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr index 1fe5d4f19a97..23df6b354450 100644 --- a/tests/ui/imports/import-from-missing-star-3.stderr +++ b/tests/ui/imports/import-from-missing-star-3.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:2:9 | LL | use spam::*; - | ^^^^ maybe a missing crate `spam`? + | ^^^^ you might be missing crate `spam` | = help: consider adding `extern crate spam` to use the `spam` crate @@ -10,7 +10,7 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:27:13 | LL | use spam::*; - | ^^^^ maybe a missing crate `spam`? + | ^^^^ you might be missing crate `spam` | = help: consider adding `extern crate spam` to use the `spam` crate diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr index f8e295078047..b311527bc28e 100644 --- a/tests/ui/imports/import-from-missing-star.stderr +++ b/tests/ui/imports/import-from-missing-star.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star.rs:1:5 | LL | use spam::*; - | ^^^^ maybe a missing crate `spam`? + | ^^^^ you might be missing crate `spam` | = help: consider adding `extern crate spam` to use the `spam` crate diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index 80b0a7f06199..06260ef9ebc7 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `main` --> $DIR/import3.rs:2:5 | LL | use main::bar; - | ^^^^ maybe a missing crate `main`? + | ^^^^ you might be missing crate `main` | = help: consider adding `extern crate main` to use the `main` crate diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr index 1b95fcf55679..fe06eddeada6 100644 --- a/tests/ui/imports/issue-109343.stderr +++ b/tests/ui/imports/issue-109343.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `unresolved` --> $DIR/issue-109343.rs:4:9 | LL | pub use unresolved::f; - | ^^^^^^^^^^ maybe a missing crate `unresolved`? + | ^^^^^^^^^^ you might be missing crate `unresolved` | = help: consider adding `extern crate unresolved` to use the `unresolved` crate diff --git a/tests/ui/imports/issue-1697.rs b/tests/ui/imports/issue-1697.rs index 5cd76d21f91c..8ec48d4d2862 100644 --- a/tests/ui/imports/issue-1697.rs +++ b/tests/ui/imports/issue-1697.rs @@ -1,6 +1,8 @@ // Testing that we don't fail abnormally after hitting the errors -use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432] - //~^ maybe a missing crate `unresolved`? +use unresolved::*; +//~^ ERROR unresolved import `unresolved` [E0432] +//~| NOTE you might be missing crate `unresolved` +//~| HELP consider adding `extern crate unresolved` to use the `unresolved` crate fn main() {} diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr index 840608ca2a14..df2957b8f2b1 100644 --- a/tests/ui/imports/issue-1697.stderr +++ b/tests/ui/imports/issue-1697.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `unresolved` --> $DIR/issue-1697.rs:3:5 | LL | use unresolved::*; - | ^^^^^^^^^^ maybe a missing crate `unresolved`? + | ^^^^^^^^^^ you might be missing crate `unresolved` | = help: consider adding `extern crate unresolved` to use the `unresolved` crate diff --git a/tests/ui/imports/issue-33464.stderr b/tests/ui/imports/issue-33464.stderr index c4e5c5558991..17cc0e4469e4 100644 --- a/tests/ui/imports/issue-33464.stderr +++ b/tests/ui/imports/issue-33464.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `abc` --> $DIR/issue-33464.rs:3:5 | LL | use abc::one_el; - | ^^^ maybe a missing crate `abc`? + | ^^^ you might be missing crate `abc` | = help: consider adding `extern crate abc` to use the `abc` crate @@ -10,7 +10,7 @@ error[E0432]: unresolved import `abc` --> $DIR/issue-33464.rs:5:5 | LL | use abc::{a, bbb, cccccc}; - | ^^^ maybe a missing crate `abc`? + | ^^^ you might be missing crate `abc` | = help: consider adding `extern crate abc` to use the `abc` crate @@ -18,7 +18,7 @@ error[E0432]: unresolved import `a_very_long_name` --> $DIR/issue-33464.rs:7:5 | LL | use a_very_long_name::{el, el2}; - | ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`? + | ^^^^^^^^^^^^^^^^ you might be missing crate `a_very_long_name` | = help: consider adding `extern crate a_very_long_name` to use the `a_very_long_name` crate diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr index e9b632d2718c..3c136df83fe4 100644 --- a/tests/ui/imports/issue-36881.stderr +++ b/tests/ui/imports/issue-36881.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `issue_36881_aux` --> $DIR/issue-36881.rs:5:9 | LL | use issue_36881_aux::Foo; - | ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`? + | ^^^^^^^^^^^^^^^ you might be missing crate `issue_36881_aux` | = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr index e7792ac0d159..36020707405f 100644 --- a/tests/ui/imports/issue-37887.stderr +++ b/tests/ui/imports/issue-37887.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `test` --> $DIR/issue-37887.rs:3:9 | LL | use test::*; - | ^^^^ maybe a missing crate `test`? + | ^^^^ you might be missing crate `test` | = help: consider adding `extern crate test` to use the `test` crate diff --git a/tests/ui/imports/issue-53269.stderr b/tests/ui/imports/issue-53269.stderr index 29c7556dac43..317b3c633a65 100644 --- a/tests/ui/imports/issue-53269.stderr +++ b/tests/ui/imports/issue-53269.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `nonexistent_module` --> $DIR/issue-53269.rs:6:9 | LL | use nonexistent_module::mac; - | ^^^^^^^^^^^^^^^^^^ maybe a missing crate `nonexistent_module`? + | ^^^^^^^^^^^^^^^^^^ you might be missing crate `nonexistent_module` | = help: consider adding `extern crate nonexistent_module` to use the `nonexistent_module` crate diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index 09bb13a06047..e9126e6575c0 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -11,7 +11,7 @@ error[E0432]: unresolved import `non_existent` --> $DIR/issue-55457.rs:2:5 | LL | use non_existent::non_existent; - | ^^^^^^^^^^^^ maybe a missing crate `non_existent`? + | ^^^^^^^^^^^^ you might be missing crate `non_existent` | = help: consider adding `extern crate non_existent` to use the `non_existent` crate diff --git a/tests/ui/imports/issue-81413.stderr b/tests/ui/imports/issue-81413.stderr index c2a321250118..321b3695d2cc 100644 --- a/tests/ui/imports/issue-81413.stderr +++ b/tests/ui/imports/issue-81413.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `doesnt_exist` --> $DIR/issue-81413.rs:7:9 | LL | pub use doesnt_exist::*; - | ^^^^^^^^^^^^ maybe a missing crate `doesnt_exist`? + | ^^^^^^^^^^^^ you might be missing crate `doesnt_exist` | = help: consider adding `extern crate doesnt_exist` to use the `doesnt_exist` crate diff --git a/tests/ui/imports/tool-mod-child.rs b/tests/ui/imports/tool-mod-child.rs index 4581dc2e2ad8..a8249ab01dfc 100644 --- a/tests/ui/imports/tool-mod-child.rs +++ b/tests/ui/imports/tool-mod-child.rs @@ -1,7 +1,7 @@ use clippy::a; //~ ERROR unresolved import `clippy` -use clippy::a::b; //~ ERROR failed to resolve: maybe a missing crate `clippy`? +use clippy::a::b; //~ ERROR failed to resolve: you might be missing crate `clippy` use rustdoc::a; //~ ERROR unresolved import `rustdoc` -use rustdoc::a::b; //~ ERROR failed to resolve: maybe a missing crate `rustdoc`? +use rustdoc::a::b; //~ ERROR failed to resolve: you might be missing crate `rustdoc` fn main() {} diff --git a/tests/ui/imports/tool-mod-child.stderr b/tests/ui/imports/tool-mod-child.stderr index 6caf15bc7240..764256e76f04 100644 --- a/tests/ui/imports/tool-mod-child.stderr +++ b/tests/ui/imports/tool-mod-child.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: maybe a missing crate `clippy`? +error[E0433]: failed to resolve: you might be missing crate `clippy` --> $DIR/tool-mod-child.rs:2:5 | LL | use clippy::a::b; - | ^^^^^^ maybe a missing crate `clippy`? + | ^^^^^^ you might be missing crate `clippy` | = help: consider adding `extern crate clippy` to use the `clippy` crate @@ -10,15 +10,15 @@ error[E0432]: unresolved import `clippy` --> $DIR/tool-mod-child.rs:1:5 | LL | use clippy::a; - | ^^^^^^ maybe a missing crate `clippy`? + | ^^^^^^ you might be missing crate `clippy` | = help: consider adding `extern crate clippy` to use the `clippy` crate -error[E0433]: failed to resolve: maybe a missing crate `rustdoc`? +error[E0433]: failed to resolve: you might be missing crate `rustdoc` --> $DIR/tool-mod-child.rs:5:5 | LL | use rustdoc::a::b; - | ^^^^^^^ maybe a missing crate `rustdoc`? + | ^^^^^^^ you might be missing crate `rustdoc` | = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate @@ -26,7 +26,7 @@ error[E0432]: unresolved import `rustdoc` --> $DIR/tool-mod-child.rs:4:5 | LL | use rustdoc::a; - | ^^^^^^^ maybe a missing crate `rustdoc`? + | ^^^^^^^ you might be missing crate `rustdoc` | = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate diff --git a/tests/ui/imports/unresolved-imports-used.stderr b/tests/ui/imports/unresolved-imports-used.stderr index 73f9d1bfb6c6..1cbc2356320f 100644 --- a/tests/ui/imports/unresolved-imports-used.stderr +++ b/tests/ui/imports/unresolved-imports-used.stderr @@ -14,7 +14,7 @@ error[E0432]: unresolved import `foo` --> $DIR/unresolved-imports-used.rs:11:5 | LL | use foo::bar; - | ^^^ maybe a missing crate `foo`? + | ^^^ you might be missing crate `foo` | = help: consider adding `extern crate foo` to use the `foo` crate @@ -22,7 +22,7 @@ error[E0432]: unresolved import `baz` --> $DIR/unresolved-imports-used.rs:12:5 | LL | use baz::*; - | ^^^ maybe a missing crate `baz`? + | ^^^ you might be missing crate `baz` | = help: consider adding `extern crate baz` to use the `baz` crate @@ -30,7 +30,7 @@ error[E0432]: unresolved import `foo2` --> $DIR/unresolved-imports-used.rs:14:5 | LL | use foo2::bar2; - | ^^^^ maybe a missing crate `foo2`? + | ^^^^ you might be missing crate `foo2` | = help: consider adding `extern crate foo2` to use the `foo2` crate @@ -38,7 +38,7 @@ error[E0432]: unresolved import `baz2` --> $DIR/unresolved-imports-used.rs:15:5 | LL | use baz2::*; - | ^^^^ maybe a missing crate `baz2`? + | ^^^^ you might be missing crate `baz2` | = help: consider adding `extern crate baz2` to use the `baz2` crate diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index 54ee45c28679..a647ca27f1c2 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -13,7 +13,7 @@ error[E0432]: unresolved import `r#extern` --> $DIR/keyword-extern-as-identifier-use.rs:1:5 | LL | use extern::foo; - | ^^^^^^ maybe a missing crate `r#extern`? + | ^^^^^^ you might be missing crate `r#extern` | = help: consider adding `extern crate r#extern` to use the `r#extern` crate diff --git a/tests/ui/macros/meta-item-absolute-path.stderr b/tests/ui/macros/meta-item-absolute-path.stderr index f0d763d7abba..af56d935284c 100644 --- a/tests/ui/macros/meta-item-absolute-path.stderr +++ b/tests/ui/macros/meta-item-absolute-path.stderr @@ -1,14 +1,14 @@ -error[E0433]: failed to resolve: maybe a missing crate `Absolute`? +error[E0433]: failed to resolve: you might be missing crate `Absolute` --> $DIR/meta-item-absolute-path.rs:1:12 | LL | #[derive(::Absolute)] - | ^^^^^^^^ maybe a missing crate `Absolute`? + | ^^^^^^^^ you might be missing crate `Absolute` -error[E0433]: failed to resolve: maybe a missing crate `Absolute`? +error[E0433]: failed to resolve: you might be missing crate `Absolute` --> $DIR/meta-item-absolute-path.rs:1:12 | LL | #[derive(::Absolute)] - | ^^^^^^^^ maybe a missing crate `Absolute`? + | ^^^^^^^^ you might be missing crate `Absolute` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/privacy/restricted/test.rs b/tests/ui/privacy/restricted/test.rs index e1d87cfcd88c..3fdfd191b365 100644 --- a/tests/ui/privacy/restricted/test.rs +++ b/tests/ui/privacy/restricted/test.rs @@ -47,6 +47,6 @@ fn main() { } mod pathological { - pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: maybe a missing crate `bad`? + pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: you might be missing crate `bad` pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules } diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index 76f19525df53..a48bb671d9f8 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: maybe a missing crate `bad`? +error[E0433]: failed to resolve: you might be missing crate `bad` --> $DIR/test.rs:50:12 | LL | pub(in bad::path) mod m1 {} - | ^^^ maybe a missing crate `bad`? + | ^^^ you might be missing crate `bad` | = help: consider adding `extern crate bad` to use the `bad` crate diff --git a/tests/ui/resolve/editions-crate-root-2015.rs b/tests/ui/resolve/editions-crate-root-2015.rs index 5f764d3ceef8..869f4c82c8b7 100644 --- a/tests/ui/resolve/editions-crate-root-2015.rs +++ b/tests/ui/resolve/editions-crate-root-2015.rs @@ -2,10 +2,10 @@ mod inner { fn global_inner(_: ::nonexistant::Foo) { - //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`? + //~^ ERROR failed to resolve: you might be missing crate `nonexistant` } fn crate_inner(_: crate::nonexistant::Foo) { - //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`? + //~^ ERROR failed to resolve: you might be missing crate `nonexistant` } fn bare_global(_: ::nonexistant) { diff --git a/tests/ui/resolve/editions-crate-root-2015.stderr b/tests/ui/resolve/editions-crate-root-2015.stderr index 00cdd0c58f4e..74fb7e6019ff 100644 --- a/tests/ui/resolve/editions-crate-root-2015.stderr +++ b/tests/ui/resolve/editions-crate-root-2015.stderr @@ -1,16 +1,16 @@ -error[E0433]: failed to resolve: maybe a missing crate `nonexistant`? +error[E0433]: failed to resolve: you might be missing crate `nonexistant` --> $DIR/editions-crate-root-2015.rs:4:26 | LL | fn global_inner(_: ::nonexistant::Foo) { - | ^^^^^^^^^^^ maybe a missing crate `nonexistant`? + | ^^^^^^^^^^^ you might be missing crate `nonexistant` | = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate -error[E0433]: failed to resolve: maybe a missing crate `nonexistant`? +error[E0433]: failed to resolve: you might be missing crate `nonexistant` --> $DIR/editions-crate-root-2015.rs:7:30 | LL | fn crate_inner(_: crate::nonexistant::Foo) { - | ^^^^^^^^^^^ maybe a missing crate `nonexistant`? + | ^^^^^^^^^^^ you might be missing crate `nonexistant` | = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate diff --git a/tests/ui/resolve/extern-prelude-fail.stderr b/tests/ui/resolve/extern-prelude-fail.stderr index a1591914b4d2..4c2d5abb7824 100644 --- a/tests/ui/resolve/extern-prelude-fail.stderr +++ b/tests/ui/resolve/extern-prelude-fail.stderr @@ -2,15 +2,15 @@ error[E0432]: unresolved import `extern_prelude` --> $DIR/extern-prelude-fail.rs:7:9 | LL | use extern_prelude::S; - | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` | = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate -error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`? +error[E0433]: failed to resolve: you might be missing crate `extern_prelude` --> $DIR/extern-prelude-fail.rs:8:15 | LL | let s = ::extern_prelude::S; - | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` | = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate diff --git a/tests/ui/resolve/issue-82865.rs b/tests/ui/resolve/issue-82865.rs index 07d88c413bfa..29a898906e96 100644 --- a/tests/ui/resolve/issue-82865.rs +++ b/tests/ui/resolve/issue-82865.rs @@ -2,7 +2,7 @@ #![feature(decl_macro)] -use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`? +use x::y::z; //~ ERROR: failed to resolve: you might be missing crate `x` macro mac () { Box::z //~ ERROR: no function or associated item diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 730fd6d60264..ce0061a2b665 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: maybe a missing crate `x`? +error[E0433]: failed to resolve: you might be missing crate `x` --> $DIR/issue-82865.rs:5:5 | LL | use x::y::z; - | ^ maybe a missing crate `x`? + | ^ you might be missing crate `x` | = help: consider adding `extern crate x` to use the `x` crate diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr index 2ac41b87562e..8e4757354030 100644 --- a/tests/ui/resolve/resolve-bad-visibility.stderr +++ b/tests/ui/resolve/resolve-bad-visibility.stderr @@ -16,19 +16,19 @@ error[E0742]: visibilities can only be restricted to ancestor modules LL | pub(in std::vec) struct F; | ^^^^^^^^ -error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? +error[E0433]: failed to resolve: you might be missing crate `nonexistent` --> $DIR/resolve-bad-visibility.rs:7:8 | LL | pub(in nonexistent) struct G; - | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | ^^^^^^^^^^^ you might be missing crate `nonexistent` | = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate -error[E0433]: failed to resolve: maybe a missing crate `too_soon`? +error[E0433]: failed to resolve: you might be missing crate `too_soon` --> $DIR/resolve-bad-visibility.rs:8:8 | LL | pub(in too_soon) struct H; - | ^^^^^^^^ maybe a missing crate `too_soon`? + | ^^^^^^^^ you might be missing crate `too_soon` | = help: consider adding `extern crate too_soon` to use the `too_soon` crate diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr index c331236a4601..0c836a614f8b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-102156.stderr @@ -1,19 +1,19 @@ -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/issue-102156.rs:4:5 | LL | use core::convert::{From, TryFrom}; | ^^^^ | | - | maybe a missing crate `core`? + | you might be missing crate `core` | help: try using `std` instead of `core`: `std` -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/issue-102156.rs:4:5 | LL | use core::convert::{From, TryFrom}; | ^^^^ | | - | maybe a missing crate `core`? + | you might be missing crate `core` | help: try using `std` instead of `core`: `std` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/simd/portable-intrinsics-arent-exposed.stderr b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr index a6f27af428b5..d38667f750d9 100644 --- a/tests/ui/simd/portable-intrinsics-arent-exposed.stderr +++ b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: maybe a missing crate `core`? +error[E0433]: failed to resolve: you might be missing crate `core` --> $DIR/portable-intrinsics-arent-exposed.rs:4:5 | LL | use core::simd::intrinsics; | ^^^^ | | - | maybe a missing crate `core`? + | you might be missing crate `core` | help: try using `std` instead of `core`: `std` error[E0432]: unresolved import `std::simd::intrinsics` diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr index 5016c41e8a57..240742996e12 100644 --- a/tests/ui/underscore-imports/issue-110164.stderr +++ b/tests/ui/underscore-imports/issue-110164.stderr @@ -38,7 +38,7 @@ error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:8:5 | LL | use _::*; - | ^ maybe a missing crate `_`? + | ^ you might be missing crate `_` | = help: consider adding `extern crate _` to use the `_` crate @@ -46,7 +46,7 @@ error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:5:5 | LL | use _::a; - | ^ maybe a missing crate `_`? + | ^ you might be missing crate `_` | = help: consider adding `extern crate _` to use the `_` crate @@ -54,7 +54,7 @@ error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:13:9 | LL | use _::a; - | ^ maybe a missing crate `_`? + | ^ you might be missing crate `_` | = help: consider adding `extern crate _` to use the `_` crate @@ -62,7 +62,7 @@ error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:16:9 | LL | use _::*; - | ^ maybe a missing crate `_`? + | ^ you might be missing crate `_` | = help: consider adding `extern crate _` to use the `_` crate diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr index 24ac2f8e6213..299ec699775e 100644 --- a/tests/ui/unresolved/unresolved-asterisk-imports.stderr +++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `not_existing_crate` --> $DIR/unresolved-asterisk-imports.rs:1:5 | LL | use not_existing_crate::*; - | ^^^^^^^^^^^^^^^^^^ maybe a missing crate `not_existing_crate`? + | ^^^^^^^^^^^^^^^^^^ you might be missing crate `not_existing_crate` | = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index 4125c593c747..e8f3b323e337 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -1,21 +1,25 @@ -use foo::bar; //~ ERROR unresolved import `foo` [E0432] - //~^ maybe a missing crate `foo`? - //~| HELP consider adding `extern crate foo` to use the `foo` crate +use foo::bar; +//~^ ERROR unresolved import `foo` [E0432] +//~| NOTE you might be missing crate `foo` +//~| HELP consider adding `extern crate foo` to use the `foo` crate -use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432] - //~| no `Baz` in `bar` - //~| HELP a similar name exists in the module - //~| SUGGESTION Bar +use bar::Baz as x; +//~^ ERROR unresolved import `bar::Baz` [E0432] +//~| NOTE no `Baz` in `bar` +//~| HELP a similar name exists in the module +//~| SUGGESTION Bar -use food::baz; //~ ERROR unresolved import `food::baz` - //~| no `baz` in `food` - //~| HELP a similar name exists in the module - //~| SUGGESTION bag +use food::baz; +//~^ ERROR unresolved import `food::baz` +//~| NOTE no `baz` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION bag -use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432] - //~| no `beens` in `food` - //~| HELP a similar name exists in the module - //~| SUGGESTION beans +use food::{beens as Foo}; +//~^ ERROR unresolved import `food::beens` [E0432] +//~| NOTE no `beens` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION beans mod bar { pub struct Bar; @@ -36,9 +40,10 @@ mod m { MyVariant } - use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION self::MyEnum + use MyEnum::*; + //~^ ERROR unresolved import `MyEnum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::MyEnum } mod items { @@ -46,9 +51,10 @@ mod items { Variant } - use Enum::*; //~ ERROR unresolved import `Enum` [E0432] - //~| HELP a similar path exists - //~| SUGGESTION self::Enum + use Enum::*; + //~^ ERROR unresolved import `Enum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::Enum fn item() {} } diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index 0dd928c8b6ff..7b03717c827c 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -2,12 +2,12 @@ error[E0432]: unresolved import `foo` --> $DIR/unresolved-import.rs:1:5 | LL | use foo::bar; - | ^^^ maybe a missing crate `foo`? + | ^^^ you might be missing crate `foo` | = help: consider adding `extern crate foo` to use the `foo` crate error[E0432]: unresolved import `bar::Baz` - --> $DIR/unresolved-import.rs:5:5 + --> $DIR/unresolved-import.rs:6:5 | LL | use bar::Baz as x; | ^^^^^---^^^^^ @@ -16,7 +16,7 @@ LL | use bar::Baz as x; | no `Baz` in `bar` error[E0432]: unresolved import `food::baz` - --> $DIR/unresolved-import.rs:10:5 + --> $DIR/unresolved-import.rs:12:5 | LL | use food::baz; | ^^^^^^--- @@ -25,7 +25,7 @@ LL | use food::baz; | no `baz` in `food` error[E0432]: unresolved import `food::beens` - --> $DIR/unresolved-import.rs:15:12 + --> $DIR/unresolved-import.rs:18:12 | LL | use food::{beens as Foo}; | -----^^^^^^^ @@ -34,13 +34,13 @@ LL | use food::{beens as Foo}; | help: a similar name exists in the module: `beans` error[E0432]: unresolved import `MyEnum` - --> $DIR/unresolved-import.rs:39:9 + --> $DIR/unresolved-import.rs:43:9 | LL | use MyEnum::*; | ^^^^^^ help: a similar path exists: `self::MyEnum` error[E0432]: unresolved import `Enum` - --> $DIR/unresolved-import.rs:49:9 + --> $DIR/unresolved-import.rs:54:9 | LL | use Enum::*; | ^^^^ help: a similar path exists: `self::Enum` From 9bd7680b2e0f1f5680b04fdb2401bad3e082fa38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 24 Jul 2024 21:06:24 +0000 Subject: [PATCH 34/49] Fix ddltool-failed test --- tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr index 0c5a06e68b89..90cca83d1c1f 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr @@ -1,6 +1,6 @@ error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX: - $DLLTOOL: Syntax error in def file $DEF_FILE:1 + $DLLTOOL: Syntax error in def file $DEF_FILE:1␍ error: aborting due to 1 previous error From 0919d0714ec49773d3a4c3a589b7651655b1b7c0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jul 2024 17:19:41 -0400 Subject: [PATCH 35/49] Don't ICE when auto trait has assoc ty in old solver --- .../src/traits/project.rs | 6 +++ tests/crashes/117829-2.rs | 14 ------- tests/crashes/117829.rs | 9 ----- tests/ui/auto-traits/assoc-ty.current.stderr | 40 +++++++++++++++++++ tests/ui/auto-traits/assoc-ty.next.stderr | 40 +++++++++++++++++++ tests/ui/auto-traits/assoc-ty.rs | 17 ++++++++ 6 files changed, 103 insertions(+), 23 deletions(-) delete mode 100644 tests/crashes/117829-2.rs delete mode 100644 tests/crashes/117829.rs create mode 100644 tests/ui/auto-traits/assoc-ty.current.stderr create mode 100644 tests/ui/auto-traits/assoc-ty.next.stderr create mode 100644 tests/ui/auto-traits/assoc-ty.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 1d7a05150444..b96e0c8a9775 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1202,6 +1202,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( false } } + } else if tcx.trait_is_auto(trait_ref.def_id) { + tcx.dcx().span_delayed_bug( + tcx.def_span(obligation.predicate.def_id), + "associated types not allowed on auto traits", + ); + false } else { bug!("unexpected builtin trait with associated type: {trait_ref:?}") } diff --git a/tests/crashes/117829-2.rs b/tests/crashes/117829-2.rs deleted file mode 100644 index ecfd3148569d..000000000000 --- a/tests/crashes/117829-2.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: #117829 -#![feature(auto_traits)] - -trait B {} - -auto trait Z -where - T: Z, - >::W: B, -{ - type W; -} - -fn main() {} diff --git a/tests/crashes/117829.rs b/tests/crashes/117829.rs deleted file mode 100644 index 7544b5ec0fce..000000000000 --- a/tests/crashes/117829.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #117829 -auto trait Z<'a, T: ?Sized> -where - T: Z<'a, u16>, - - for<'b> >::W: Clone, -{ - type W: ?Sized; -} diff --git a/tests/ui/auto-traits/assoc-ty.current.stderr b/tests/ui/auto-traits/assoc-ty.current.stderr new file mode 100644 index 000000000000..77a1c8fb654f --- /dev/null +++ b/tests/ui/auto-traits/assoc-ty.current.stderr @@ -0,0 +1,40 @@ +error[E0380]: auto traits cannot have associated items + --> $DIR/assoc-ty.rs:10:10 + | +LL | auto trait Trait { + | ----- auto traits cannot have associated items +LL | +LL | type Output; + | -----^^^^^^- help: remove these associated items + +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/assoc-ty.rs:8:1 + | +LL | / auto trait Trait { +LL | | +LL | | type Output; +LL | | +LL | | } + | |_^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/assoc-ty.rs:15:36 + | +LL | let _: <() as Trait>::Output = (); + | --------------------- ^^ expected associated type, found `()` + | | + | expected due to this + | + = note: expected associated type `<() as Trait>::Output` + found unit type `()` + = help: consider constraining the associated type `<() as Trait>::Output` to `()` or calling a method that returns `<() as Trait>::Output` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0380, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/auto-traits/assoc-ty.next.stderr b/tests/ui/auto-traits/assoc-ty.next.stderr new file mode 100644 index 000000000000..b9f56d6c99c4 --- /dev/null +++ b/tests/ui/auto-traits/assoc-ty.next.stderr @@ -0,0 +1,40 @@ +error[E0380]: auto traits cannot have associated items + --> $DIR/assoc-ty.rs:10:10 + | +LL | auto trait Trait { + | ----- auto traits cannot have associated items +LL | +LL | type Output; + | -----^^^^^^- help: remove these associated items + +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/assoc-ty.rs:8:1 + | +LL | / auto trait Trait { +LL | | +LL | | type Output; +LL | | +LL | | } + | |_^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/assoc-ty.rs:15:36 + | +LL | let _: <() as Trait>::Output = (); + | --------------------- ^^ types differ + | | + | expected due to this + | + = note: expected associated type `<() as Trait>::Output` + found unit type `()` + = help: consider constraining the associated type `<() as Trait>::Output` to `()` or calling a method that returns `<() as Trait>::Output` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0380, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/auto-traits/assoc-ty.rs b/tests/ui/auto-traits/assoc-ty.rs new file mode 100644 index 000000000000..ada75147f6ea --- /dev/null +++ b/tests/ui/auto-traits/assoc-ty.rs @@ -0,0 +1,17 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// Tests that projection doesn't explode if we accidentally +// put an associated type on an auto trait. + +auto trait Trait { + //~^ ERROR auto traits are experimental and possibly buggy + type Output; + //~^ ERROR auto traits cannot have associated items +} + +fn main() { + let _: <() as Trait>::Output = (); + //~^ ERROR mismatched types +} From 2c7ae388b34a2cd8a38a27320c7a5ed2654cd632 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 24 Jul 2024 11:42:31 -0700 Subject: [PATCH 36/49] std: unsafe-wrap gcc::rust_eh_personality and impl --- library/std/src/sys/personality/gcc.rs | 285 +++++++++++++------------ 1 file changed, 151 insertions(+), 134 deletions(-) diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 0dc53550ca94..5542cf03d20c 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -35,6 +35,7 @@ //! //! Once stack has been unwound down to the handler frame level, unwinding stops //! and the last personality routine transfers control to the catch block. +#![forbid(unsafe_op_in_unsafe_fn)] use super::dwarf::eh::{self, EHAction, EHContext}; use crate::ffi::c_int; @@ -92,7 +93,11 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c cfg_if::cfg_if! { - if #[cfg(all(not(all(target_vendor = "apple", not(target_os = "watchos"))), target_arch = "arm", not(target_os = "netbsd")))] { + if #[cfg(all( + target_arch = "arm", + not(all(target_vendor = "apple", not(target_os = "watchos"))), + not(target_os = "netbsd"), + ))] { // ARM EHABI personality routine. // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf // @@ -104,90 +109,94 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - let state = state as c_int; - let action = state & uw::_US_ACTION_MASK as c_int; - let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { - // Backtraces on ARM will call the personality routine with - // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases - // we want to continue unwinding the stack, otherwise all our backtraces - // would end at __rust_try - if state & uw::_US_FORCE_UNWIND as c_int != 0 { - return continue_unwind(exception_object, context); - } - true - } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { - false - } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int { - return continue_unwind(exception_object, context); - } else { - return uw::_URC_FAILURE; - }; - - // The DWARF unwinder assumes that _Unwind_Context holds things like the function - // and LSDA pointers, however ARM EHABI places them into the exception object. - // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which - // take only the context pointer, GCC personality routines stash a pointer to - // exception_object in the context, using location reserved for ARM's - // "scratch register" (r12). - uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); - // ...A more principled approach would be to provide the full definition of ARM's - // _Unwind_Context in our libunwind bindings and fetch the required data from there - // directly, bypassing DWARF compatibility functions. - - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FAILURE, - }; - if search_phase { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => { + unsafe { + let state = state as c_int; + let action = state & uw::_US_ACTION_MASK as c_int; + let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { + // Backtraces on ARM will call the personality routine with + // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases + // we want to continue unwinding the stack, otherwise all our backtraces + // would end at __rust_try + if state & uw::_US_FORCE_UNWIND as c_int != 0 { return continue_unwind(exception_object, context); } - EHAction::Catch(_) | EHAction::Filter(_) => { - // EHABI requires the personality routine to update the - // SP value in the barrier cache of the exception object. - (*exception_object).private[5] = - uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG); - return uw::_URC_HANDLER_FOUND; - } - EHAction::Terminate => return uw::_URC_FAILURE, - } - } else { - match eh_action { - EHAction::None => return continue_unwind(exception_object, context), - EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object as uw::_Unwind_Ptr, - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - return uw::_URC_INSTALL_CONTEXT; - } - EHAction::Terminate => return uw::_URC_FAILURE, - } - } - - // On ARM EHABI the personality routine is responsible for actually - // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). - unsafe fn continue_unwind( - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON { - uw::_URC_CONTINUE_UNWIND + true + } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { + false + } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int { + return continue_unwind(exception_object, context); } else { - uw::_URC_FAILURE + return uw::_URC_FAILURE; + }; + + // The DWARF unwinder assumes that _Unwind_Context holds things like the function + // and LSDA pointers, however ARM EHABI places them into the exception object. + // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which + // take only the context pointer, GCC personality routines stash a pointer to + // exception_object in the context, using location reserved for ARM's + // "scratch register" (r12). + uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); + // ...A more principled approach would be to provide the full definition of ARM's + // _Unwind_Context in our libunwind bindings and fetch the required data from there + // directly, bypassing DWARF compatibility functions. + + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FAILURE, + }; + if search_phase { + match eh_action { + EHAction::None | EHAction::Cleanup(_) => { + return continue_unwind(exception_object, context); + } + EHAction::Catch(_) | EHAction::Filter(_) => { + // EHABI requires the personality routine to update the + // SP value in the barrier cache of the exception object. + (*exception_object).private[5] = + uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG); + return uw::_URC_HANDLER_FOUND; + } + EHAction::Terminate => return uw::_URC_FAILURE, + } + } else { + match eh_action { + EHAction::None => return continue_unwind(exception_object, context), + EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { + uw::_Unwind_SetGR( + context, + UNWIND_DATA_REG.0, + exception_object as uw::_Unwind_Ptr, + ); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); + uw::_Unwind_SetIP(context, lpad); + return uw::_URC_INSTALL_CONTEXT; + } + EHAction::Terminate => return uw::_URC_FAILURE, + } } - } - // defined in libgcc - extern "C" { - fn __gnu_unwind_frame( + + // On ARM EHABI the personality routine is responsible for actually + // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). + unsafe fn continue_unwind( exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code; + ) -> uw::_Unwind_Reason_Code { + unsafe { + if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON { + uw::_URC_CONTINUE_UNWIND + } else { + uw::_URC_FAILURE + } + } + } + // defined in libgcc + extern "C" { + fn __gnu_unwind_frame( + exception_object: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context, + ) -> uw::_Unwind_Reason_Code; + } } } } else { @@ -200,35 +209,37 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - if version != 1 { - return uw::_URC_FATAL_PHASE1_ERROR; - } - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, - }; - if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, - EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, + unsafe { + if version != 1 { + return uw::_URC_FATAL_PHASE1_ERROR; } - } else { - match eh_action { - EHAction::None => uw::_URC_CONTINUE_UNWIND, - // Forced unwinding hits a terminate action. - EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object.cast(), - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - uw::_URC_INSTALL_CONTEXT + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, + }; + if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { + match eh_action { + EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, + EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, + EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, + } + } else { + match eh_action { + EHAction::None => uw::_URC_CONTINUE_UNWIND, + // Forced unwinding hits a terminate action. + EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { + uw::_Unwind_SetGR( + context, + UNWIND_DATA_REG.0, + exception_object.cast(), + ); + uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); + uw::_Unwind_SetIP(context, lpad); + uw::_URC_INSTALL_CONTEXT + } + EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, } - EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, } } } @@ -245,13 +256,15 @@ cfg_if::cfg_if! { contextRecord: *mut uw::CONTEXT, dispatcherContext: *mut uw::DISPATCHER_CONTEXT, ) -> uw::EXCEPTION_DISPOSITION { - uw::_GCC_specific_handler( - exceptionRecord, - establisherFrame, - contextRecord, - dispatcherContext, - rust_eh_personality_impl, - ) + unsafe { + uw::_GCC_specific_handler( + exceptionRecord, + establisherFrame, + contextRecord, + dispatcherContext, + rust_eh_personality_impl, + ) + } } } else { // The personality routine for most of our targets. @@ -263,13 +276,15 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { - rust_eh_personality_impl( - version, - actions, - exception_class, - exception_object, - context, - ) + unsafe { + rust_eh_personality_impl( + version, + actions, + exception_class, + exception_object, + context, + ) + } } } } @@ -277,18 +292,20 @@ cfg_if::cfg_if! { } unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result { - let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; - let mut ip_before_instr: c_int = 0; - let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); - let eh_context = EHContext { - // The return address points 1 byte past the call instruction, - // which could be in the next IP range in LSDA range table. - // - // `ip = -1` has special meaning, so use wrapping sub to allow for that - ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, - func_start: uw::_Unwind_GetRegionStart(context), - get_text_start: &|| uw::_Unwind_GetTextRelBase(context), - get_data_start: &|| uw::_Unwind_GetDataRelBase(context), - }; - eh::find_eh_action(lsda, &eh_context) + unsafe { + let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; + let mut ip_before_instr: c_int = 0; + let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); + let eh_context = EHContext { + // The return address points 1 byte past the call instruction, + // which could be in the next IP range in LSDA range table. + // + // `ip = -1` has special meaning, so use wrapping sub to allow for that + ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, + func_start: uw::_Unwind_GetRegionStart(context), + get_text_start: &|| uw::_Unwind_GetTextRelBase(context), + get_data_start: &|| uw::_Unwind_GetDataRelBase(context), + }; + eh::find_eh_action(lsda, &eh_context) + } } From c9cd4a68532fb963cc8b9074242848baa3bd73cc Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 24 Jul 2024 11:53:56 -0700 Subject: [PATCH 37/49] std: update comments on gcc personality fn --- library/std/src/sys/personality/gcc.rs | 42 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index 5542cf03d20c..1fb85a10179c 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -98,11 +98,12 @@ cfg_if::cfg_if! { not(all(target_vendor = "apple", not(target_os = "watchos"))), not(target_os = "netbsd"), ))] { - // ARM EHABI personality routine. - // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf - // - // Apple 32-bit ARM (but not watchOS) uses the default routine instead - // since it uses SjLj unwinding. + /// personality fn called by [ARM EHABI][armeabi-eh] + /// + /// Apple 32-bit ARM (but not watchOS) uses the default routine instead + /// since it uses "setjmp-longjmp" unwinding. + /// + /// [armeabi-eh]: https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( state: uw::_Unwind_State, @@ -200,8 +201,8 @@ cfg_if::cfg_if! { } } } else { - // Default personality routine, which is used directly on most targets - // and indirectly on Windows x86_64 via SEH. + /// Default personality routine, which is used directly on most targets + /// and indirectly on Windows x86_64 and AArch64 via SEH. unsafe extern "C" fn rust_eh_personality_impl( version: c_int, actions: uw::_Unwind_Action, @@ -246,8 +247,12 @@ cfg_if::cfg_if! { cfg_if::cfg_if! { if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { - // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind - // handler data (aka LSDA) uses GCC-compatible encoding. + /// personality fn called by [Windows Structured Exception Handling][windows-eh] + /// + /// On x86_64 and AArch64 MinGW targets, the unwinding mechanism is SEH, + /// however the unwind handler data (aka LSDA) uses GCC-compatible encoding + /// + /// [windows-eh]: https://learn.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170 #[lang = "eh_personality"] #[allow(nonstandard_style)] unsafe extern "C" fn rust_eh_personality( @@ -256,6 +261,9 @@ cfg_if::cfg_if! { contextRecord: *mut uw::CONTEXT, dispatcherContext: *mut uw::DISPATCHER_CONTEXT, ) -> uw::EXCEPTION_DISPOSITION { + // SAFETY: the cfg is still target_os = "windows" and target_env = "gnu", + // which means that this is the correct function to call, passing our impl fn + // as the callback which gets actually used unsafe { uw::_GCC_specific_handler( exceptionRecord, @@ -267,7 +275,19 @@ cfg_if::cfg_if! { } } } else { - // The personality routine for most of our targets. + /// personality fn called by [Itanium C++ ABI Exception Handling][itanium-eh] + /// + /// The personality routine for most non-Windows targets. This will be called by + /// the unwinding library: + /// - "In the search phase, the framework repeatedly calls the personality routine, + /// with the _UA_SEARCH_PHASE flag as described below, first for the current PC + /// and register state, and then unwinding a frame to a new PC at each step..." + /// - "If the search phase reports success, the framework restarts in the cleanup + /// phase. Again, it repeatedly calls the personality routine, with the + /// _UA_CLEANUP_PHASE flag as described below, first for the current PC and + /// register state, and then unwinding a frame to a new PC at each step..."i + /// + /// [itanium-eh]: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( version: c_int, @@ -276,6 +296,8 @@ cfg_if::cfg_if! { exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code { + // SAFETY: the platform support must modify the cfg for the inner fn + // if it needs something different than what is currently invoked. unsafe { rust_eh_personality_impl( version, From 7da751a108a31b52650d055202e89a15f43ce0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 25 Jul 2024 02:47:53 +0200 Subject: [PATCH 38/49] Apply suggestions from code review --- compiler/rustc_parse/src/parser/ty.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a2db4b6feef7..b2a0742f2119 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -927,8 +927,12 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"] + /// CONSTNESS = [["~"] "const"] + /// ASYNCNESS = ["async"] + /// POLARITY = ["?" | "!"] /// ``` + /// + /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers. fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { let modifier_lo = self.token.span; let constness = if self.eat(&token::Tilde) { @@ -1007,7 +1011,7 @@ impl<'a> Parser<'a> { /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - /// TY_BOUND_NOPAREN = [for] [TRAIT_BOUND_MODIFIERS] SIMPLE_PATH + /// TY_BOUND_NOPAREN = [for CONSTNESS ASYNCNESS | POLARITY] SIMPLE_PATH /// ``` /// /// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`. From 40d132f0f826b0f0ae203219ab30d23da8f55573 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jul 2024 22:59:38 -0400 Subject: [PATCH 39/49] Make sure that args are compatible in resolve_associated_item --- compiler/rustc_ty_utils/src/instance.rs | 15 +++++++-- tests/crashes/120792.rs | 25 --------------- tests/crashes/120793-2.rs | 22 ------------- tests/crashes/120793.rs | 21 ------------ tests/crashes/121063.rs | 20 ------------ tests/crashes/121957-1.rs | 20 ------------ tests/crashes/121957-2.rs | 20 ------------ .../inline-incorrect-early-bound.rs | 27 ++++++++++++++++ .../inline-incorrect-early-bound.stderr | 15 +++++++++ .../inline-incorrect-early-bound-in-ctfe.rs | 32 +++++++++++++++++++ ...nline-incorrect-early-bound-in-ctfe.stderr | 21 ++++++++++++ 11 files changed, 108 insertions(+), 130 deletions(-) delete mode 100644 tests/crashes/120792.rs delete mode 100644 tests/crashes/120793-2.rs delete mode 100644 tests/crashes/120793.rs delete mode 100644 tests/crashes/121063.rs delete mode 100644 tests/crashes/121957-1.rs delete mode 100644 tests/crashes/121957-2.rs create mode 100644 tests/ui/polymorphization/inline-incorrect-early-bound.rs create mode 100644 tests/ui/polymorphization/inline-incorrect-early-bound.stderr create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.stderr diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 7b6d86d22a57..a2bed61a7ae1 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -191,11 +191,22 @@ fn resolve_associated_item<'tcx>( // Any final impl is required to define all associated items. if !leaf_def.item.defaultness(tcx).has_value() { - let guard = tcx.dcx().span_delayed_bug( + let guar = tcx.dcx().span_delayed_bug( tcx.def_span(leaf_def.item.def_id), "missing value for assoc item in impl", ); - return Err(guard); + return Err(guar); + } + + // Make sure that we're projecting to an item that has compatible args. + // This may happen if we are resolving an instance before codegen, such + // as during inlining. This check is also done in projection. + if !tcx.check_args_compatible(leaf_def.item.def_id, args) { + let guar = tcx.dcx().span_delayed_bug( + tcx.def_span(leaf_def.item.def_id), + "missing value for assoc item in impl", + ); + return Err(guar); } let args = tcx.erase_regions(args); diff --git a/tests/crashes/120792.rs b/tests/crashes/120792.rs deleted file mode 100644 index 51889251787d..000000000000 --- a/tests/crashes/120792.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #120792 -//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes - -impl Trait<()> for () { - fn foo<'a, K>(self, _: (), _: K) { - todo!(); - } -} - -trait Foo {} - -impl Foo for F { - fn main() { - ().foo((), ()); - } -} - -trait Trait { - fn foo<'a, K>(self, _: T, _: K) - where - T: 'a, - K: 'a; -} - -pub fn main() {} diff --git a/tests/crashes/120793-2.rs b/tests/crashes/120793-2.rs deleted file mode 100644 index 0ce5e4df2247..000000000000 --- a/tests/crashes/120793-2.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #120793 -// can't use build-fail, because this also fails check-fail, but -// the ICE from #120787 only reproduces on build-fail. -//@ compile-flags: --emit=mir - -#![feature(effects)] - -trait Dim { - fn dim() -> usize; -} - -enum Dim3 {} - -impl Dim for Dim3 { - fn dim(x: impl Sized) -> usize { - 3 - } -} - -fn main() { - [0; Dim3::dim()]; -} diff --git a/tests/crashes/120793.rs b/tests/crashes/120793.rs deleted file mode 100644 index 7e9166a50e55..000000000000 --- a/tests/crashes/120793.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: #120793 -#![feature(effects)] - -trait Dim { - fn dim() -> usize; -} - -enum Dim3 {} - -impl Dim for Dim3 { - fn dim(mut x: impl Iterator) -> usize { - 3 - } -} - -fn main() { - let array: [usize; Dim3::dim()] - //~^ ERROR E0015 - = [0; Dim3::dim()]; - //~^ ERROR E0015 -} diff --git a/tests/crashes/121063.rs b/tests/crashes/121063.rs deleted file mode 100644 index cb9db2853c2a..000000000000 --- a/tests/crashes/121063.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #121063 -//@ compile-flags: -Zpolymorphize=on --edition=2021 -Zinline-mir=yes - -use std::{ - fmt, ops, - path::{Component, Path, PathBuf}, -}; - -pub struct AbsPathBuf(PathBuf); - -impl TryFrom for AbsPathBuf { - type Error = PathBuf; - fn try_from(path: impl AsRef) -> Result {} -} - -impl TryFrom<&str> for AbsPathBuf { - fn try_from(path: &str) -> Result { - AbsPathBuf::try_from(PathBuf::from(path)) - } -} diff --git a/tests/crashes/121957-1.rs b/tests/crashes/121957-1.rs deleted file mode 100644 index 74b4649cc9d9..000000000000 --- a/tests/crashes/121957-1.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #121957 -#![feature(const_trait_impl, effects)] - -#[const_trait] -trait Main { - fn compute() -> u32; -} - -impl const Main for () { - fn compute<'x, 'y, 'z: 'x>() -> u32 {} -} - -#[const_trait] -trait Aux {} - -impl const Aux for () {} - -fn main() { - const _: u32 = <()>::compute::<()>(); -} diff --git a/tests/crashes/121957-2.rs b/tests/crashes/121957-2.rs deleted file mode 100644 index 74b4649cc9d9..000000000000 --- a/tests/crashes/121957-2.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #121957 -#![feature(const_trait_impl, effects)] - -#[const_trait] -trait Main { - fn compute() -> u32; -} - -impl const Main for () { - fn compute<'x, 'y, 'z: 'x>() -> u32 {} -} - -#[const_trait] -trait Aux {} - -impl const Aux for () {} - -fn main() { - const _: u32 = <()>::compute::<()>(); -} diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.rs b/tests/ui/polymorphization/inline-incorrect-early-bound.rs new file mode 100644 index 000000000000..e69e4a4faa05 --- /dev/null +++ b/tests/ui/polymorphization/inline-incorrect-early-bound.rs @@ -0,0 +1,27 @@ +// This test demonstrates an ICE that may occur when we try to resolve the instance +// of a impl that has different generics than the trait it's implementing. This ensures +// we first check that the args are compatible before resolving the body, just like +// we do in projection before substituting a GAT. +// +// When polymorphization is enabled, we check the optimized MIR for unused parameters. +// This will invoke the inliner, leading to this ICE. + +//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes + +trait Trait { + fn foo<'a, K: 'a>(self, _: K); +} + +impl Trait for () { + #[inline] + fn foo(self, _: K) { + //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration + todo!(); + } +} + +pub fn qux() { + ().foo(()); +} + +fn main() {} diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.stderr b/tests/ui/polymorphization/inline-incorrect-early-bound.stderr new file mode 100644 index 000000000000..3a1d05e8a361 --- /dev/null +++ b/tests/ui/polymorphization/inline-incorrect-early-bound.stderr @@ -0,0 +1,15 @@ +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/inline-incorrect-early-bound.rs:17:11 + | +LL | fn foo<'a, K: 'a>(self, _: K); + | ----------- + | | | + | | this bound might be missing in the impl + | lifetimes in impl do not match this method in trait +... +LL | fn foo(self, _: K) { + | ^^^ lifetimes do not match method in trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.rs new file mode 100644 index 000000000000..e3adcce17b42 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.rs @@ -0,0 +1,32 @@ +// This test demonstrates an ICE that may occur when we try to resolve the instance +// of a impl that has different generics than the trait it's implementing. This ensures +// we first check that the args are compatible before resolving the body, just like +// we do in projection before substituting a GAT. +// +// Const traits aren't the only way to achieve this ICE, but it's a convenient way +// to ensure the inliner is called. + +//@ compile-flags: -Znext-solver -Zinline-mir=yes + +#![feature(const_trait_impl, effects)] +//~^ WARN the feature `effects` is incomplete + +trait Trait { + fn foo(self); +} + +impl Trait for () { + #[inline] + fn foo(self) { + //~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters + todo!(); + } +} + +const fn foo() { + ().foo(); +} + +const UWU: () = foo(); + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.stderr new file mode 100644 index 000000000000..2e7801c0b8ac --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/inline-incorrect-early-bound-in-ctfe.stderr @@ -0,0 +1,21 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:11:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:20:12 + | +LL | fn foo(self); + | - expected 0 type parameters +... +LL | fn foo(self) { + | ^ found 1 type parameter + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0049`. From d004edf311eef38e91a6cd490629c60b55d16e09 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jul 2024 23:36:42 -0400 Subject: [PATCH 40/49] Don't ICE if HIR and middle types disagree in borrowck error reporting --- .../src/diagnostics/conflict_errors.rs | 34 +++++++++++++----- tests/crashes/121816.rs | 12 ------- tests/ui/borrowck/ice-on-non-ref-sig-ty.rs | 19 ++++++++++ .../ui/borrowck/ice-on-non-ref-sig-ty.stderr | 36 +++++++++++++++++++ 4 files changed, 81 insertions(+), 20 deletions(-) delete mode 100644 tests/crashes/121816.rs create mode 100644 tests/ui/borrowck/ice-on-non-ref-sig-ty.rs create mode 100644 tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index b147567001db..2d9bc45ebc82 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { // search for relevant arguments. let mut arguments = Vec::new(); for (index, argument) in sig.inputs().skip_binder().iter().enumerate() { - if let ty::Ref(argument_region, _, _) = argument.kind() { - if argument_region == return_region { - // Need to use the `rustc_middle::ty` types to compare against the - // `return_region`. Then use the `rustc_hir` type to get only - // the lifetime span. - if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind { + if let ty::Ref(argument_region, _, _) = argument.kind() + && argument_region == return_region + { + // Need to use the `rustc_middle::ty` types to compare against the + // `return_region`. Then use the `rustc_hir` type to get only + // the lifetime span. + match &fn_decl.inputs[index].kind { + hir::TyKind::Ref(lifetime, _) => { // With access to the lifetime, we can get // the span of it. arguments.push((*argument, lifetime.ident.span)); - } else { - bug!("ty type is a ref but hir type is not"); + } + // Resolve `self` whose self type is `&T`. + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + if let Res::SelfTyAlias { alias_to, .. } = path.res + && let Some(alias_to) = alias_to.as_local() + && let hir::Impl { self_ty, .. } = self + .infcx + .tcx + .hir_node_by_def_id(alias_to) + .expect_item() + .expect_impl() + && let hir::TyKind::Ref(lifetime, _) = self_ty.kind + { + arguments.push((*argument, lifetime.ident.span)); + } + } + _ => { + // Don't ICE though. It might be a type alias. } } } diff --git a/tests/crashes/121816.rs b/tests/crashes/121816.rs deleted file mode 100644 index a5569ea19d3e..000000000000 --- a/tests/crashes/121816.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #121816 -fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T { - x -} -trait W<'a> { - fn g(self, x: &'a T) -> &'static T; -} -impl<'a> W<'a> for &'static () { - fn g(self, x: &'a T) -> &'static T { - f(&self, x) - } -} diff --git a/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs b/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs new file mode 100644 index 000000000000..1c867bd2378d --- /dev/null +++ b/tests/ui/borrowck/ice-on-non-ref-sig-ty.rs @@ -0,0 +1,19 @@ +// Don't ICE when trying to annotate signature and we see `&()` + +fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T { + x +} +trait W<'a> { + fn g(self, x: &'a T) -> &'static T; +} + +// Frankly this error message is impossible to parse, but :shrug:. +impl<'a> W<'a> for &'static () { + fn g(self, x: &'a T) -> &'static T { + f(&self, x) + //~^ ERROR borrowed data escapes outside of method + //~| ERROR `self` does not live long enough + } +} + +fn main() {} diff --git a/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr new file mode 100644 index 000000000000..2b900a8e68a7 --- /dev/null +++ b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr @@ -0,0 +1,36 @@ +error[E0521]: borrowed data escapes outside of method + --> $DIR/ice-on-non-ref-sig-ty.rs:13:9 + | +LL | impl<'a> W<'a> for &'static () { + | -- lifetime `'a` defined here +LL | fn g(self, x: &'a T) -> &'static T { + | ---- - `x` is a reference that is only valid in the method body + | | + | `self` declared here, outside of the method body +LL | f(&self, x) + | ^^^^^^^^^^^ + | | + | `x` escapes the method body here + | argument requires that `'a` must outlive `'static` + +error[E0597]: `self` does not live long enough + --> $DIR/ice-on-non-ref-sig-ty.rs:13:11 + | +LL | impl<'a> W<'a> for &'static () { + | ------- has lifetime `'static` +LL | fn g(self, x: &'a T) -> &'static T { + | ------- also has lifetime `'static` +LL | f(&self, x) + | ^^^^^ `self` would have to be valid for `'static`... +... +LL | } + | - ...but `self` will be dropped here, when the function `g` returns + | + = help: use data from the highlighted arguments which match the `'static` lifetime of the return type + = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments + = note: to learn more, visit + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. From 34819b72983af230c3e413371a096e94c684a5e5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jul 2024 23:49:21 -0400 Subject: [PATCH 41/49] Don't add crashes for misuses of intrinsics --- tests/crashes/101962.rs | 11 ----------- tests/crashes/111699.rs | 14 -------------- tests/crashes/97501.rs | 22 ---------------------- 3 files changed, 47 deletions(-) delete mode 100644 tests/crashes/101962.rs delete mode 100644 tests/crashes/111699.rs delete mode 100644 tests/crashes/97501.rs diff --git a/tests/crashes/101962.rs b/tests/crashes/101962.rs deleted file mode 100644 index b6a78ce053af..000000000000 --- a/tests/crashes/101962.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #101962 - -#![feature(core_intrinsics)] - -pub fn wrapping(a: T, b: T) { - let _z = core::intrinsics::wrapping_mul(a, b); -} - -fn main() { - wrapping(1,2); -} diff --git a/tests/crashes/111699.rs b/tests/crashes/111699.rs deleted file mode 100644 index 5ba17c2aa1af..000000000000 --- a/tests/crashes/111699.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: #111699 -//@ edition:2021 -//@ compile-flags: -Copt-level=0 -#![feature(core_intrinsics)] -use std::intrinsics::offset; - -fn main() { - let a = [1u8, 2, 3]; - let ptr: *const u8 = a.as_ptr(); - - unsafe { - assert_eq!(*offset(ptr, 0), 1); - } -} diff --git a/tests/crashes/97501.rs b/tests/crashes/97501.rs deleted file mode 100644 index 51a83d8be169..000000000000 --- a/tests/crashes/97501.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #97501 - -#![feature(core_intrinsics)] -use std::intrinsics::wrapping_add; - -#[derive(Clone, Copy)] -struct WrapInt8 { - value: u8 -} - -impl std::ops::Add for WrapInt8 { - type Output = WrapInt8; - fn add(self, other: WrapInt8) -> WrapInt8 { - wrapping_add(self, other) - } -} - -fn main() { - let p = WrapInt8 { value: 123 }; - let q = WrapInt8 { value: 234 }; - println!("{}", (p + q).value); -} From 17b4fbc388ec11a3c1cdf7e33ff00a0322edaf98 Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Thu, 25 Jul 2024 15:11:26 +0530 Subject: [PATCH 42/49] In connect timeout, read readiness of socket for vxworks. Check pollhup or pollerr for refused connections in linux --- library/std/src/sys/pal/unix/net.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs index b8dc1538a637..092c3ee594d0 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/pal/unix/net.rs @@ -213,16 +213,25 @@ impl Socket { } 0 => {} _ => { - // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look - // for POLLHUP rather than read readiness - if pollfd.revents & libc::POLLHUP != 0 { - let e = self.take_error()?.unwrap_or_else(|| { - io::const_io_error!( - io::ErrorKind::Uncategorized, - "no error set after POLLHUP", - ) - }); - return Err(e); + if cfg!(target_os = "vxworks") { + // VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the + // connnection actually succeeded and return ok only when the socket is + // ready and no errors were found. + if let Some(e) = self.take_error()? { + return Err(e); + } + } else { + // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look + // for POLLHUP or POLLERR rather than read readiness + if pollfd.revents & (libc::POLLHUP | libc::POLLERR) != 0 { + let e = self.take_error()?.unwrap_or_else(|| { + io::const_io_error!( + io::ErrorKind::Uncategorized, + "no error set after POLLHUP", + ) + }); + return Err(e); + } } return Ok(()); From cf9816c17e1c265af2906a8a5a7c025be3f3dccb Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 24 Jul 2024 15:28:31 +0300 Subject: [PATCH 43/49] CStr: derive PartialEq, Eq; add test for Ord --- library/core/src/ffi/c_str.rs | 15 ++++----------- library/core/tests/ffi.rs | 1 + library/core/tests/ffi/cstr.rs | 15 +++++++++++++++ library/core/tests/lib.rs | 1 + 4 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 library/core/tests/ffi.rs create mode 100644 library/core/tests/ffi/cstr.rs diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index c9111254082d..ae42ae3baf41 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -94,7 +94,7 @@ use crate::str; /// ``` /// /// [str]: prim@str "str" -#[derive(Hash)] +#[derive(PartialEq, Eq, Hash)] #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] @@ -104,7 +104,6 @@ use crate::str; // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. #[repr(transparent)] -#[allow(clippy::derived_hash_with_manual_eq)] pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with // just a raw `c_char` along with some form of marker to make @@ -678,15 +677,9 @@ impl CStr { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for CStr { - #[inline] - fn eq(&self, other: &CStr) -> bool { - self.to_bytes().eq(other.to_bytes()) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for CStr {} +// `.to_bytes()` representations are compared instead of the inner `[c_char]`s, +// because `c_char` is `i8` (not `u8`) on some platforms. +// That is why this is implemented manually and not derived. #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for CStr { #[inline] diff --git a/library/core/tests/ffi.rs b/library/core/tests/ffi.rs new file mode 100644 index 000000000000..2b33fbd95f07 --- /dev/null +++ b/library/core/tests/ffi.rs @@ -0,0 +1 @@ +mod cstr; diff --git a/library/core/tests/ffi/cstr.rs b/library/core/tests/ffi/cstr.rs new file mode 100644 index 000000000000..9bf4c21a9ab9 --- /dev/null +++ b/library/core/tests/ffi/cstr.rs @@ -0,0 +1,15 @@ +use core::ffi::CStr; + +#[test] +fn compares_as_u8s() { + let a: &CStr = c"Hello!"; // Starts with ascii + let a_bytes: &[u8] = a.to_bytes(); + assert!((..0b1000_0000).contains(&a_bytes[0])); + + let b: &CStr = c"こんにちは!"; // Starts with non ascii + let b_bytes: &[u8] = b.to_bytes(); + assert!((0b1000_0000..).contains(&b_bytes[0])); + + assert_eq!(Ord::cmp(a, b), Ord::cmp(a_bytes, b_bytes)); + assert_eq!(PartialOrd::partial_cmp(a, b), PartialOrd::partial_cmp(a_bytes, b_bytes)); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 83a615fcd8be..04aaa3f35b7a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -132,6 +132,7 @@ mod clone; mod cmp; mod const_ptr; mod convert; +mod ffi; mod fmt; mod future; mod hash; From 4ac60601d32d96688494c4bb404a04205501a02b Mon Sep 17 00:00:00 2001 From: surechen Date: Thu, 25 Jul 2024 22:33:45 +0800 Subject: [PATCH 44/49] Fix a span error when parsing a wrong param of function. fixes #128042 --- compiler/rustc_parse/src/parser/item.rs | 9 +++++++- .../suggest-add-self-issue-128042.rs | 12 ++++++++++ .../suggest-add-self-issue-128042.stderr | 22 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/ui/suggestions/suggest-add-self-issue-128042.rs create mode 100644 tests/ui/suggestions/suggest-add-self-issue-128042.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index fbc5b9146003..9aaf4b99243f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2773,7 +2773,14 @@ impl<'a> Parser<'a> { let snapshot = p.create_snapshot_for_diagnostic(); let param = p.parse_param_general(req_name, first_param).or_else(|e| { let guar = e.emit(); - let lo = p.prev_token.span; + // When parsing a param failed, we should check to make the span of the param + // not contain '(' before it. + // For example when parsing `*mut Self` in function `fn oof(*mut Self)`. + let lo = if let TokenKind::OpenDelim(Delimiter::Parenthesis) = p.prev_token.kind { + p.prev_token.span.shrink_to_hi() + } else { + p.prev_token.span + }; p.restore_snapshot(snapshot); // Skip every token until next possible arg or end. p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(Delimiter::Parenthesis)]); diff --git a/tests/ui/suggestions/suggest-add-self-issue-128042.rs b/tests/ui/suggestions/suggest-add-self-issue-128042.rs new file mode 100644 index 000000000000..f94d166c4967 --- /dev/null +++ b/tests/ui/suggestions/suggest-add-self-issue-128042.rs @@ -0,0 +1,12 @@ +struct Thing { + state: u8, +} + +impl Thing { + fn oof(*mut Self) { //~ ERROR expected parameter name, found `*` + self.state = 1; + //~^ ERROR expected value, found module `self` + } +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-add-self-issue-128042.stderr b/tests/ui/suggestions/suggest-add-self-issue-128042.stderr new file mode 100644 index 000000000000..49ac15632501 --- /dev/null +++ b/tests/ui/suggestions/suggest-add-self-issue-128042.stderr @@ -0,0 +1,22 @@ +error: expected parameter name, found `*` + --> $DIR/suggest-add-self-issue-128042.rs:6:12 + | +LL | fn oof(*mut Self) { + | ^ expected parameter name + +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self-issue-128042.rs:7:9 + | +LL | fn oof(*mut Self) { + | --- this function doesn't have a `self` parameter +LL | self.state = 1; + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn oof(&self, *mut Self) { + | ++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0424`. From f0ba8c4ffb092469fe603f16074fcc5a60dc8eb6 Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:57:57 +0200 Subject: [PATCH 45/49] Fix 1.80.0 version in RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 0ecd472efb6e..2c91ddf78267 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -Version 1.80 (2024-07-25) +Version 1.80.0 (2024-07-25) ========================== From 0706cc6397cfe51bbffdefa134e6459a0f7c049a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Jul 2024 15:33:34 +0000 Subject: [PATCH 46/49] Turn an unreachable code path into an ICE --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 99afb500e0b6..5f13b329de40 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -3,7 +3,6 @@ use crate::thir::cx::region::Scope; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; use itertools::Itertools; -use rustc_ast::LitKind; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -22,8 +21,7 @@ use rustc_middle::ty::{ self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType, }; use rustc_middle::{bug, span_bug}; -use rustc_span::source_map::Spanned; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{sym, Span}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use tracing::{debug, info, instrument, trace}; @@ -899,14 +897,10 @@ impl<'tcx> Cx<'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local()); let generics = self.tcx.generics_of(hir_id.owner); let Some(&index) = generics.param_def_id_to_index.get(&def_id) else { - let guar = self.tcx.dcx().has_errors().unwrap(); - // We already errored about a late bound const - - let lit = self - .tcx - .hir_arena - .alloc(Spanned { span: DUMMY_SP, node: LitKind::Err(guar) }); - return ExprKind::Literal { lit, neg: false }; + span_bug!( + expr.span, + "Should have already errored about late bound consts: {def_id:?}" + ); }; let name = self.tcx.hir().name(hir_id); let param = ty::ParamConst::new(index, name); From 38931cd227a9e177ddb749da26ce03f2eb6532aa Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 25 Jul 2024 16:47:30 +0000 Subject: [PATCH 47/49] LLVM: LLVM-20.0 removes MMX types See llvm/llvm-project#98505 --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 -- compiler/rustc_codegen_ssa/src/common.rs | 1 - compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 2 -- 3 files changed, 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ae46200d3f55..3beda28ac1fd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -305,7 +305,6 @@ pub enum TypeKind { Pointer = 12, Vector = 13, Metadata = 14, - X86_MMX = 15, Token = 16, ScalableVector = 17, BFloat = 18, @@ -330,7 +329,6 @@ impl TypeKind { TypeKind::Pointer => rustc_codegen_ssa::common::TypeKind::Pointer, TypeKind::Vector => rustc_codegen_ssa::common::TypeKind::Vector, TypeKind::Metadata => rustc_codegen_ssa::common::TypeKind::Metadata, - TypeKind::X86_MMX => rustc_codegen_ssa::common::TypeKind::X86_MMX, TypeKind::Token => rustc_codegen_ssa::common::TypeKind::Token, TypeKind::ScalableVector => rustc_codegen_ssa::common::TypeKind::ScalableVector, TypeKind::BFloat => rustc_codegen_ssa::common::TypeKind::BFloat, diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 27b0f127e926..ea2fd482e1fc 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -91,7 +91,6 @@ pub enum TypeKind { Pointer, Vector, Metadata, - X86_MMX, Token, ScalableVector, BFloat, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 14757b27a375..4cdd8af1008c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1419,8 +1419,6 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { return LLVMPointerTypeKind; case Type::FixedVectorTyID: return LLVMVectorTypeKind; - case Type::X86_MMXTyID: - return LLVMX86_MMXTypeKind; case Type::TokenTyID: return LLVMTokenTypeKind; case Type::ScalableVectorTyID: From 8174f9b44b91fbcddfb1dfe667195e21a305fea9 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 25 Jul 2024 19:47:12 +0100 Subject: [PATCH 48/49] Stop using `unsized_const_parameters` in core/std --- library/core/src/intrinsics/simd.rs | 12 ------------ library/core/src/lib.rs | 1 - library/core/src/marker.rs | 2 ++ .../miri/tests/pass/intrinsics/portable-simd.rs | 15 ++++++++++++++- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 30734c020b39..0c21e6f31a82 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -243,18 +243,6 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_shuffle(x: T, y: T, idx: U) -> V; - /// Shuffle two vectors by const indices. - /// - /// `T` must be a vector. - /// - /// `U` must be a vector with the same element type as `T` and the same length as `IDX`. - /// - /// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy` - /// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds - /// of `xy`. - #[rustc_nounwind] - pub fn simd_shuffle_generic(x: T, y: T) -> U; - /// Read a vector of pointers. /// /// `T` must be a vector. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0ec46412e952..02cb02dce1d8 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -249,7 +249,6 @@ #![feature(transparent_unions)] #![feature(try_blocks)] #![feature(unboxed_closures)] -#![feature(unsized_const_params)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] // tidy-alphabetical-end diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index a87528033c03..cf428e36ea7a 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -42,6 +42,8 @@ use crate::hash::Hasher; /// } /// ``` #[unstable(feature = "internal_impls_macro", issue = "none")] +// Allow implementations of `UnsizedConstParamTy` even though std cannot use that feature. +#[allow_internal_unstable(unsized_const_params)] macro marker_impls { ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => { $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {} diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index 03d9fc0a76fe..c4ba11d0a436 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -1,10 +1,23 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(portable_simd, adt_const_params, core_intrinsics, repr_simd)] +#![feature( + portable_simd, + unsized_const_params, + adt_const_params, + rustc_attrs, + intrinsics, + core_intrinsics, + repr_simd +)] #![allow(incomplete_features, internal_features)] use std::intrinsics::simd as intrinsics; use std::ptr; use std::simd::{prelude::*, StdFloat}; +extern "rust-intrinsic" { + #[rustc_nounwind] + pub fn simd_shuffle_generic(x: T, y: T) -> U; +} + fn simd_ops_f32() { let a = f32x4::splat(10.0); let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]); From e141b071640964cc626faa8dcf69ddcb1e24b4a7 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Thu, 25 Jul 2024 15:27:20 -0700 Subject: [PATCH 49/49] fix: compilation issue w/ refactored type --- library/std/src/sys/pal/windows/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 15d446786add..ea19bd1e9619 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -416,8 +416,8 @@ impl File { dwHighDateTime: (info.LastWriteTime >> 32) as u32, }, change_time: Some(c::FILETIME { - dhLowDateTime: info.ChangeTime as c::DWORD, - dhHighDateTime: (info.ChangeTime >> 32) as c::DWORD, + dwLowDateTime: info.ChangeTime as u32, + dwHighDateTime: (info.ChangeTime >> 32) as u32, }), file_size: 0, reparse_tag: 0,