diff options
196 files changed, 1694 insertions, 928 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 9d93370b7d0..f4cbfb6967f 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -45,9 +45,9 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { }; match const_.val { ConstKind::Value(_) => {} - ConstKind::Unevaluated(def, ref substs, promoted) => { + ConstKind::Unevaluated(unevaluated) => { if let Err(err) = - fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) + fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { all_constants_ok = false; match err { @@ -122,14 +122,14 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => { + ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) if fx.tcx.is_static(def.did) => { assert!(substs.is_empty()); assert!(promoted.is_none()); return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx); } - ConstKind::Unevaluated(def, ref substs, promoted) => { - match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) { + ConstKind::Unevaluated(unevaluated) => { + match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { Ok(const_val) => const_val, Err(_) => { span_bug!(constant.span, "erroneous constant not captured by required_consts"); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index d17136080fe..86df71a0dfc 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -276,5 +276,6 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // simd_bitmask // simd_select // simd_rem + // simd_neg } } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index d9393ffe534..854e3ccc21b 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -1,6 +1,7 @@ use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, AttributePlace}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -41,12 +42,29 @@ impl ArgAttributeExt for ArgAttribute { } pub trait ArgAttributesExt { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value); - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value); + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value); + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ); +} + +fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool { + // LLVM prior to version 12 has known miscompiles in the presence of + // noalias attributes (see #54878). Only enable mutable noalias by + // default for versions we believe to be safe. + cx.tcx + .sess + .opts + .debugging_opts + .mutable_noalias + .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0)) } impl ArgAttributesExt for ArgAttributes { - fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) { + fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -62,6 +80,9 @@ impl ArgAttributesExt for ArgAttributes { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_llfn(idx, llfn); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -74,7 +95,12 @@ impl ArgAttributesExt for ArgAttributes { } } - fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) { + fn apply_attrs_to_callsite( + &self, + idx: AttributePlace, + cx: &CodegenCx<'_, '_>, + callsite: &Value, + ) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -98,6 +124,9 @@ impl ArgAttributesExt for ArgAttributes { ); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); + if regular.contains(ArgAttribute::NoAliasMutRef) && should_use_mutable_noalias(cx) { + llvm::Attribute::NoAlias.apply_callsite(idx, callsite); + } match self.arg_ext { ArgExtension::None => {} ArgExtension::Zext => { @@ -419,13 +448,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), cx, llfn); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); @@ -480,18 +509,18 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. let mut i = 0; - let mut apply = |attrs: &ArgAttributes| { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite); + let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| { + attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), cx, callsite); i += 1; i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, &bx.cx, callsite); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddStructRetCallSiteAttr( callsite, @@ -517,12 +546,12 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { - let i = apply(attrs); + let i = apply(bx.cx, attrs); unsafe { llvm::LLVMRustAddByValCallSiteAttr( callsite, @@ -533,22 +562,22 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Direct(ref attrs) | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { - apply(attrs); + apply(bx.cx, attrs); } PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack: _, } => { - apply(attrs); - apply(extra_attrs); + apply(bx.cx, attrs); + apply(bx.cx, extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a); - apply(b); + apply(bx.cx, a); + apply(bx.cx, b); } PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + apply(bx.cx, &ArgAttributes::new()); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md new file mode 100644 index 00000000000..f983d092039 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md @@ -0,0 +1,180 @@ +# Debug Info Module + +This module serves the purpose of generating debug symbols. We use LLVM's +[source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) +features for generating the debug information. The general principle is +this: + +Given the right metadata in the LLVM IR, the LLVM code generator is able to +create DWARF debug symbols for the given code. The +[metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured +much like DWARF *debugging information entries* (DIE), representing type +information such as datatype layout, function signatures, block layout, +variable location and scope information, etc. It is the purpose of this +module to generate correct metadata and insert it into the LLVM IR. + +As the exact format of metadata trees may change between different LLVM +versions, we now use LLVM +[DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) +to create metadata where possible. This will hopefully ease the adaption of +this module to future LLVM versions. + +The public API of the module is a set of functions that will insert the +correct metadata into the LLVM IR when called with the right parameters. +The module is thus driven from an outside client with functions like +`debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. + +Internally the module will try to reuse already created metadata by +utilizing a cache. The way to get a shared metadata node when needed is +thus to just call the corresponding function in this module: + + let file_metadata = file_metadata(cx, file); + +The function will take care of probing the cache for an existing node for +that exact file path. + +All private state used by the module is stored within either the +CrateDebugContext struct (owned by the CodegenCx) or the +FunctionDebugContext (owned by the FunctionCx). + +This file consists of three conceptual sections: +1. The public interface of the module +2. Module-internal metadata creation functions +3. Minor utility functions + + +## Recursive Types + +Some kinds of types, such as structs and enums can be recursive. That means +that the type definition of some type X refers to some other type which in +turn (transitively) refers to X. This introduces cycles into the type +referral graph. A naive algorithm doing an on-demand, depth-first traversal +of this graph when describing types, can get trapped in an endless loop +when it reaches such a cycle. + +For example, the following simple type for a singly-linked list... + +``` +struct List { + value: i32, + tail: Option<Box<List>>, +} +``` + +will generate the following callstack with a naive DFS algorithm: + +``` +describe(t = List) + describe(t = i32) + describe(t = Option<Box<List>>) + describe(t = Box<List>) + describe(t = List) // at the beginning again... + ... +``` + +To break cycles like these, we use "forward declarations". That is, when +the algorithm encounters a possibly recursive type (any struct or enum), it +immediately creates a type description node and inserts it into the cache +*before* describing the members of the type. This type description is just +a stub (as type members are not described and added to it yet) but it +allows the algorithm to already refer to the type. After the stub is +inserted into the cache, the algorithm continues as before. If it now +encounters a recursive reference, it will hit the cache and does not try to +describe the type anew. + +This behavior is encapsulated in the 'RecursiveTypeDescription' enum, +which represents a kind of continuation, storing all state needed to +continue traversal at the type members after the type has been registered +with the cache. (This implementation approach might be a tad over- +engineered and may change in the future) + + +## Source Locations and Line Information + +In addition to data type descriptions the debugging information must also +allow to map machine code locations back to source code locations in order +to be useful. This functionality is also handled in this module. The +following functions allow to control source mappings: + ++ `set_source_location()` ++ `clear_source_location()` ++ `start_emitting_source_locations()` + +`set_source_location()` allows to set the current source location. All IR +instructions created after a call to this function will be linked to the +given source location, until another location is specified with +`set_source_location()` or the source location is cleared with +`clear_source_location()`. In the later case, subsequent IR instruction +will not be linked to any source location. As you can see, this is a +stateful API (mimicking the one in LLVM), so be careful with source +locations set by previous calls. It's probably best to not rely on any +specific state being present at a given point in code. + +One topic that deserves some extra attention is *function prologues*. At +the beginning of a function's machine code there are typically a few +instructions for loading argument values into allocas and checking if +there's enough stack space for the function to execute. This *prologue* is +not visible in the source code and LLVM puts a special PROLOGUE END marker +into the line table at the first non-prologue instruction of the function. +In order to find out where the prologue ends, LLVM looks for the first +instruction in the function body that is linked to a source location. So, +when generating prologue instructions we have to make sure that we don't +emit source location information until the 'real' function body begins. For +this reason, source location emission is disabled by default for any new +function being codegened and is only activated after a call to the third +function from the list above, `start_emitting_source_locations()`. This +function should be called right before regularly starting to codegen the +top-level block of the given function. + +There is one exception to the above rule: `llvm.dbg.declare` instruction +must be linked to the source location of the variable being declared. For +function parameters these `llvm.dbg.declare` instructions typically occur +in the middle of the prologue, however, they are ignored by LLVM's prologue +detection. The `create_argument_metadata()` and related functions take care +of linking the `llvm.dbg.declare` instructions to the correct source +locations even while source location emission is still disabled, so there +is no need to do anything special with source location handling here. + +## Unique Type Identification + +In order for link-time optimization to work properly, LLVM needs a unique +type identifier that tells it across compilation units which types are the +same as others. This type identifier is created by +`TypeMap::get_unique_type_id_of_type()` using the following algorithm: + +1. Primitive types have their name as ID + +2. Structs, enums and traits have a multipart identifier + + 1. The first part is the SVH (strict version hash) of the crate they + were originally defined in + + 2. The second part is the ast::NodeId of the definition in their + original crate + + 3. The final part is a concatenation of the type IDs of their concrete + type arguments if they are generic types. + +3. Tuple-, pointer-, and function types are structurally identified, which + means that they are equivalent if their component types are equivalent + (i.e., `(i32, i32)` is the same regardless in which crate it is used). + +This algorithm also provides a stable ID for types that are defined in one +crate but instantiated from metadata within another crate. We just have to +take care to always map crate and `NodeId`s back to the original crate +context. + +As a side-effect these unique type IDs also help to solve a problem arising +from lifetime parameters. Since lifetime parameters are completely omitted +in debuginfo, more than one `Ty` instance may map to the same debuginfo +type metadata, that is, some struct `Struct<'a>` may have N instantiations +with different concrete substitutions for `'a`, and thus there will be N +`Ty` instances for the type `Struct<'a>` even though it is not generic +otherwise. Unfortunately this means that we cannot use `ty::type_id()` as +cheap identifier for type metadata -- we have done this in the past, but it +led to unnecessary metadata duplication in the best case and LLVM +assertions in the worst. However, the unique type ID as described above +*can* be used as identifier. Since it is comparatively expensive to +construct, though, `ty::type_id()` is still used additionally as an +optimization for cases where the exact same type has been seen before +(which is most of the time). diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs b/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs deleted file mode 100644 index 10dd5906529..00000000000 --- a/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs +++ /dev/null @@ -1,179 +0,0 @@ -//! # Debug Info Module -//! -//! This module serves the purpose of generating debug symbols. We use LLVM's -//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html) -//! features for generating the debug information. The general principle is -//! this: -//! -//! Given the right metadata in the LLVM IR, the LLVM code generator is able to -//! create DWARF debug symbols for the given code. The -//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured -//! much like DWARF *debugging information entries* (DIE), representing type -//! information such as datatype layout, function signatures, block layout, -//! variable location and scope information, etc. It is the purpose of this -//! module to generate correct metadata and insert it into the LLVM IR. -//! -//! As the exact format of metadata trees may change between different LLVM -//! versions, we now use LLVM -//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) -//! to create metadata where possible. This will hopefully ease the adaption of -//! this module to future LLVM versions. -//! -//! The public API of the module is a set of functions that will insert the -//! correct metadata into the LLVM IR when called with the right parameters. -//! The module is thus driven from an outside client with functions like -//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`. -//! -//! Internally the module will try to reuse already created metadata by -//! utilizing a cache. The way to get a shared metadata node when needed is -//! thus to just call the corresponding function in this module: -//! -//! let file_metadata = file_metadata(cx, file); -//! -//! The function will take care of probing the cache for an existing node for -//! that exact file path. -//! -//! All private state used by the module is stored within either the -//! CrateDebugContext struct (owned by the CodegenCx) or the -//! FunctionDebugContext (owned by the FunctionCx). -//! -//! This file consists of three conceptual sections: -//! 1. The public interface of the module -//! 2. Module-internal metadata creation functions -//! 3. Minor utility functions -//! -//! -//! ## Recursive Types -//! -//! Some kinds of types, such as structs and enums can be recursive. That means -//! that the type definition of some type X refers to some other type which in -//! turn (transitively) refers to X. This introduces cycles into the type -//! referral graph. A naive algorithm doing an on-demand, depth-first traversal -//! of this graph when describing types, can get trapped in an endless loop -//! when it reaches such a cycle. -//! -//! For example, the following simple type for a singly-linked list... -//! -//! ``` -//! struct List { -//! value: i32, -//! tail: Option<Box<List>>, -//! } -//! ``` -//! -//! will generate the following callstack with a naive DFS algorithm: -//! -//! ``` -//! describe(t = List) -//! describe(t = i32) -//! describe(t = Option<Box<List>>) -//! describe(t = Box<List>) -//! describe(t = List) // at the beginning again... -//! ... -//! ``` -//! -//! To break cycles like these, we use "forward declarations". That is, when -//! the algorithm encounters a possibly recursive type (any struct or enum), it -//! immediately creates a type description node and inserts it into the cache -//! *before* describing the members of the type. This type description is just -//! a stub (as type members are not described and added to it yet) but it -//! allows the algorithm to already refer to the type. After the stub is -//! inserted into the cache, the algorithm continues as before. If it now -//! encounters a recursive reference, it will hit the cache and does not try to -//! describe the type anew. -//! -//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum, -//! which represents a kind of continuation, storing all state needed to -//! continue traversal at the type members after the type has been registered -//! with the cache. (This implementation approach might be a tad over- -//! engineered and may change in the future) -//! -//! -//! ## Source Locations and Line Information -//! -//! In addition to data type descriptions the debugging information must also -//! allow to map machine code locations back to source code locations in order -//! to be useful. This functionality is also handled in this module. The -//! following functions allow to control source mappings: -//! -//! + set_source_location() -//! + clear_source_location() -//! + start_emitting_source_locations() -//! -//! `set_source_location()` allows to set the current source location. All IR -//! instructions created after a call to this function will be linked to the -//! given source location, until another location is specified with -//! `set_source_location()` or the source location is cleared with -//! `clear_source_location()`. In the later case, subsequent IR instruction -//! will not be linked to any source location. As you can see, this is a -//! stateful API (mimicking the one in LLVM), so be careful with source -//! locations set by previous calls. It's probably best to not rely on any -//! specific state being present at a given point in code. -//! -//! One topic that deserves some extra attention is *function prologues*. At -//! the beginning of a function's machine code there are typically a few -//! instructions for loading argument values into allocas and checking if -//! there's enough stack space for the function to execute. This *prologue* is -//! not visible in the source code and LLVM puts a special PROLOGUE END marker -//! into the line table at the first non-prologue instruction of the function. -//! In order to find out where the prologue ends, LLVM looks for the first -//! instruction in the function body that is linked to a source location. So, -//! when generating prologue instructions we have to make sure that we don't -//! emit source location information until the 'real' function body begins. For -//! this reason, source location emission is disabled by default for any new -//! function being codegened and is only activated after a call to the third -//! function from the list above, `start_emitting_source_locations()`. This -//! function should be called right before regularly starting to codegen the -//! top-level block of the given function. -//! -//! There is one exception to the above rule: `llvm.dbg.declare` instruction -//! must be linked to the source location of the variable being declared. For -//! function parameters these `llvm.dbg.declare` instructions typically occur -//! in the middle of the prologue, however, they are ignored by LLVM's prologue -//! detection. The `create_argument_metadata()` and related functions take care -//! of linking the `llvm.dbg.declare` instructions to the correct source -//! locations even while source location emission is still disabled, so there -//! is no need to do anything special with source location handling here. -//! -//! ## Unique Type Identification -//! -//! In order for link-time optimization to work properly, LLVM needs a unique -//! type identifier that tells it across compilation units which types are the -//! same as others. This type identifier is created by -//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm: -//! -//! (1) Primitive types have their name as ID -//! (2) Structs, enums and traits have a multipart identifier -//! -//! (1) The first part is the SVH (strict version hash) of the crate they -//! were originally defined in -//! -//! (2) The second part is the ast::NodeId of the definition in their -//! original crate -//! -//! (3) The final part is a concatenation of the type IDs of their concrete -//! type arguments if they are generic types. -//! -//! (3) Tuple-, pointer and function types are structurally identified, which -//! means that they are equivalent if their component types are equivalent -//! (i.e., (i32, i32) is the same regardless in which crate it is used). -//! -//! This algorithm also provides a stable ID for types that are defined in one -//! crate but instantiated from metadata within another crate. We just have to -//! take care to always map crate and `NodeId`s back to the original crate -//! context. -//! -//! As a side-effect these unique type IDs also help to solve a problem arising -//! from lifetime parameters. Since lifetime parameters are completely omitted -//! in debuginfo, more than one `Ty` instance may map to the same debuginfo -//! type metadata, that is, some struct `Struct<'a>` may have N instantiations -//! with different concrete substitutions for `'a`, and thus there will be N -//! `Ty` instances for the type `Struct<'a>` even though it is not generic -//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as -//! cheap identifier for type metadata -- we have done this in the past, but it -//! led to unnecessary metadata duplication in the best case and LLVM -//! assertions in the worst. However, the unique type ID as described above -//! *can* be used as identifier. Since it is comparatively expensive to -//! construct, though, `ty::type_id()` is still used additionally as an -//! optimization for cases where the exact same type has been seen before -//! (which is most of the time). diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 440e4d505fc..abb87cb3656 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -1,5 +1,4 @@ -// See doc.rs for documentation. -mod doc; +#![doc = include_str!("doc.md")] use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f445d708c94..af366f93b91 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1628,7 +1628,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, out_elem ); } - macro_rules! arith { + macro_rules! arith_binary { ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { $(if name == sym::$name { match in_elem.kind() { @@ -1644,7 +1644,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, })* } } - arith! { + arith_binary! { simd_add: Uint, Int => add, Float => fadd; simd_sub: Uint, Int => sub, Float => fsub; simd_mul: Uint, Int => mul, Float => fmul; @@ -1659,6 +1659,25 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, simd_fmin: Float => minnum; } + macro_rules! arith_unary { + ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { + $(if name == sym::$name { + match in_elem.kind() { + $($(ty::$p(_))|* => { + return Ok(bx.$call(args[0].immediate())) + })* + _ => {}, + } + require!(false, + "unsupported operation on `{}` with element `{}`", + in_ty, + in_elem) + })* + } + } + arith_unary! { + simd_neg: Int => neg, Float => fneg; + } if name == sym::simd_saturating_add || name == sym::simd_saturating_sub { let lhs = args[0].immediate(); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2bfb68f4904..de7f5fc6e29 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,6 +8,7 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] +#![feature(extended_key_value_attributes)] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(nll)] diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index aa41acc3578..fa8a53e60b1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -30,10 +30,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::ConstantKind::Val(val, _) => return Ok(val), }; match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => self + ty::ConstKind::Unevaluated(ct) => self .cx .tcx() - .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) + .const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None) .map_err(|err| { self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 681b49e2ea9..81b115fac0d 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -1,8 +1,5 @@ use crate::stable_hasher; -use rustc_serialize::{ - opaque::{self, EncodeResult, FileEncodeResult}, - Decodable, Encodable, -}; +use rustc_serialize::{Decodable, Encodable}; use std::hash::{Hash, Hasher}; use std::mem::{self, MaybeUninit}; @@ -63,16 +60,6 @@ impl Fingerprint { pub fn to_hex(&self) -> String { format!("{:x}{:x}", self.0, self.1) } - - pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> { - let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array(); - - decoder.read_raw_bytes(&mut bytes)?; - - let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) }; - - Ok(Fingerprint(u64::from_le(l), u64::from_le(r))) - } } impl std::fmt::Display for Fingerprint { @@ -130,55 +117,22 @@ impl stable_hasher::StableHasherResult for Fingerprint { impl_stable_hash_via_hash!(Fingerprint); impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint { + #[inline] fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.encode_fingerprint(self) + let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) }; + s.emit_raw_bytes(&bytes)?; + Ok(()) } } impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint { + #[inline] fn decode(d: &mut D) -> Result<Self, D::Error> { - d.decode_fingerprint() - } -} - -pub trait FingerprintEncoder: rustc_serialize::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>; -} - -pub trait FingerprintDecoder: rustc_serialize::Decoder { - fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error>; -} - -impl<E: rustc_serialize::Encoder> FingerprintEncoder for E { - default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> { - panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::<E>()); - } -} - -impl FingerprintEncoder for opaque::Encoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes); - Ok(()) - } -} - -impl FingerprintEncoder for opaque::FileEncoder { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult { - let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; - self.emit_raw_bytes(&bytes) - } -} - -impl<D: rustc_serialize::Decoder> FingerprintDecoder for D { - default fn decode_fingerprint(&mut self) -> Result<Fingerprint, D::Error> { - panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>()); - } -} + let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array(); + d.read_raw_bytes(&mut bytes)?; -impl FingerprintDecoder for opaque::Decoder<'_> { - fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> { - Fingerprint::decode_opaque(self) + let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) }; + Ok(Fingerprint(u64::from_le(l), u64::from_le(r))) } } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index cb41bc81225..1ea26b4eab4 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -739,9 +739,8 @@ fn ident_name_compatibility_hack( let time_macros_impl = macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs"); - if time_macros_impl - || (macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs")) - { + let js_sys = macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs"); + if time_macros_impl || js_sys { let snippet = source_map.span_to_snippet(orig_span); if snippet.as_deref() == Ok("$name") { if time_macros_impl { @@ -754,8 +753,35 @@ fn ident_name_compatibility_hack( "the `time-macros-impl` crate will stop compiling in futures version of Rust. \ Please update to the latest version of the `time` crate to avoid breakage".to_string()) ); + return Some((*ident, *is_raw)); + } + if js_sys { + if let Some(c) = path + .components() + .flat_map(|c| c.as_os_str().to_str()) + .find(|c| c.starts_with("js-sys")) + { + let mut version = c.trim_start_matches("js-sys-").split("."); + if version.next() == Some("0") + && version.next() == Some("3") + && version + .next() + .and_then(|c| c.parse::<u32>().ok()) + .map_or(false, |v| v < 40) + { + rustc.sess.buffer_lint_with_diagnostic( + &PROC_MACRO_BACK_COMPAT, + orig_span, + ast::CRATE_NODE_ID, + "using an old version of `js-sys`", + BuiltinLintDiagnostics::ProcMacroBackCompat( + "older versions of the `js-sys` crate will stop compiling in future versions of Rust; \ + please update to `js-sys` v0.3.40 or above".to_string()) + ); + return Some((*ident, *is_raw)); + } + } } - return Some((*ident, *is_raw)); } } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 374a9eb41e5..b821ed6cff9 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -15,6 +15,7 @@ use std::io::{self, Read}; use std::path::Path; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; +use rustc_serialize::Encoder; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 3df58cb7857..7b18f4d0ff6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -18,7 +18,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::mir; use rustc_middle::mir::interpret::EvalToConstValueResult; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -1499,9 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam<DefId>, - substs: SubstsRef<'tcx>, - promoted: Option<mir::Promoted>, + ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { let mut original_values = OriginalQueryValues::default(); @@ -1510,7 +1507,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (param_env, substs) = canonical.value; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env, def, substs, promoted, span) + self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span) } /// If `typ` is a type variable of some kind, resolve it one level diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 93ba2e6a4f1..b3f0c66de68 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -566,7 +566,7 @@ fn test_debugging_options_tracking_hash() { tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); - tracked!(mutable_noalias, true); + tracked!(mutable_noalias, Some(true)); tracked!(new_llvm_pass_manager, true); tracked!(no_codegen, true); tracked!(no_generate_arange_section, true); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e9b8388c1c9..e8891e471f9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,7 +7,6 @@ use crate::rmeta::*; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; @@ -351,12 +350,6 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex { } } -impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> { let cdata = decoder.cdata(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 254954c8376..ff8ec1d5513 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,7 +1,6 @@ use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; @@ -116,6 +115,7 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -307,12 +307,6 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { } } -impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { - self.opaque.encode_fingerprint(f) - } -} - impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; @@ -2064,10 +2058,10 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); - encoder.emit_raw_bytes(METADATA_HEADER); + encoder.emit_raw_bytes(METADATA_HEADER).unwrap(); // Will be filled with the root position after encoding everything. - encoder.emit_raw_bytes(&[0, 0, 0, 0]); + encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap(); let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (source_map_files[0].clone(), 0); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 03bd4170ea9..62c0ce15845 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -2,6 +2,7 @@ use crate::rmeta::*; use rustc_index::vec::Idx; use rustc_serialize::opaque::Encoder; +use rustc_serialize::Encoder as _; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -172,7 +173,7 @@ where pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> { let pos = buf.position(); - buf.emit_raw_bytes(&self.bytes); + buf.emit_raw_bytes(&self.bytes).unwrap(); Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len()) } } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 6af0b4947e8..1561b3d7d29 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -25,7 +25,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(assert_matches)] -#![feature(assoc_char_funcs)] #![feature(backtrace)] #![feature(bool_to_option)] #![feature(box_patterns)] diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs index b85f1e6e5de..776a777b1bd 100644 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ b/compiler/rustc_middle/src/mir/abstract_const.rs @@ -18,3 +18,20 @@ pub enum Node<'tcx> { UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]), } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum NotConstEvaluatable { + Error(rustc_errors::ErrorReported), + MentionsInfer, + MentionsParam, +} + +impl From<rustc_errors::ErrorReported> for NotConstEvaluatable { + fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable { + NotConstEvaluatable::Error(e) + } +} + +TrivialTypeFoldableAndLiftImpls! { + NotConstEvaluatable, +} diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 3e7b93b32a6..fa7c0670e8c 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,7 +1,7 @@ use super::{ErrorHandled, EvalToConstValueResult, GlobalId}; use crate::mir; -use crate::ty::subst::{InternalSubsts, SubstsRef}; +use crate::ty::subst::InternalSubsts; use crate::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::Span; @@ -35,14 +35,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - def: ty::WithOptConstParam<DefId>, - substs: SubstsRef<'tcx>, - promoted: Option<mir::Promoted>, + ct: ty::Unevaluated<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { - match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) { + match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted }; + let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) } Ok(None) => Err(ErrorHandled::TooGeneric), diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ae367db019b..53a7d8528d3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -993,6 +993,10 @@ rustc_queries! { query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } } + /// Query backing `TyS::is_unpin`. + query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Unpin`", env.value } + } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 0bd0a701fb2..90b82020551 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -9,7 +9,7 @@ pub mod specialization_graph; mod structural_impls; use crate::infer::canonical::Canonical; -use crate::mir::interpret::ErrorHandled; +use crate::mir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; @@ -398,7 +398,7 @@ pub enum SelectionError<'tcx> { ty::error::TypeError<'tcx>, ), TraitNotObjectSafe(DefId), - ConstEvalFailure(ErrorHandled), + NotConstEvaluatable(NotConstEvaluatable), Overflow, } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index f796534c2e1..ea1caf58d78 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -472,6 +472,11 @@ macro_rules! implement_ty_decoder { read_str -> Cow<'_, str>; } + #[inline] + fn read_raw_bytes(&mut self, bytes: &mut [std::mem::MaybeUninit<u8>]) -> Result<(), Self::Error> { + self.opaque.read_raw_bytes(bytes) + } + fn error(&mut self, err: &str) -> Self::Error { self.opaque.error(err) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 622f8e8ff6c..779d6c90f97 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -98,18 +98,18 @@ impl<'tcx> Const<'tcx> { let name = tcx.hir().name(hir_id); ty::ConstKind::Param(ty::ParamConst::new(index, name)) } - _ => ty::ConstKind::Unevaluated( - def.to_global(), - InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - None, - ), + _ => ty::ConstKind::Unevaluated(ty::Unevaluated { + def: def.to_global(), + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), + promoted: None, + }), }; tcx.mk_const(ty::Const { val, ty }) } - #[inline] /// Interns the given value as a constant. + #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 43e22ce8f87..875d8d00a93 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -12,10 +12,18 @@ use rustc_macros::HashStable; use rustc_target::abi::Size; use super::ScalarInt; +/// An unevaluated, potentially generic, constant. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] +pub struct Unevaluated<'tcx> { + pub def: ty::WithOptConstParam<DefId>, + pub substs: SubstsRef<'tcx>, + pub promoted: Option<Promoted>, +} /// Represents a constant in Rust. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -#[derive(HashStable)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(Hash, HashStable)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ty::ParamConst), @@ -31,7 +39,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Option<Promoted>), + Unevaluated(Unevaluated<'tcx>), /// Used to hold computed value. Value(ConstValue<'tcx>), @@ -102,7 +110,7 @@ impl<'tcx> ConstKind<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option<Result<ConstValue<'tcx>, ErrorReported>> { - if let ConstKind::Unevaluated(def, substs, promoted) = self { + if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self { use crate::mir::interpret::ErrorHandled; // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` @@ -132,7 +140,8 @@ impl<'tcx> ConstKind<'tcx> { let (param_env, substs) = param_env_and_substs.into_parts(); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - match tcx.const_eval_resolve(param_env, def, substs, promoted, None) { + match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None) + { // NOTE(eddyb) `val` contains no lifetimes/types/consts, // and we use the original type, so nothing from `substs` // (which may be identity substs, see above), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 6ecd1ebf370..d6dc81c5b78 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -270,10 +270,7 @@ impl FlagComputation { fn add_const(&mut self, c: &ty::Const<'_>) { self.add_ty(c.ty); match c.val { - ty::ConstKind::Unevaluated(_, substs, _) => { - self.add_substs(substs); - self.add_flags(TypeFlags::HAS_CT_PROJECTION); - } + ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated), ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { @@ -297,6 +294,11 @@ impl FlagComputation { } } + fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { + self.add_substs(ct.substs); + self.add_flags(TypeFlags::HAS_CT_PROJECTION); + } + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); self.add_ty(projection.ty); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 814581a6cf1..3a75a6d907d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -11,7 +11,7 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ @@ -2318,31 +2318,30 @@ where ty::Ref(_, ty, mt) if offset.bytes() == 0 => { let address_space = addr_space_of_ty(ty); let tcx = cx.tcx(); - let is_freeze = ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()); - let kind = match mt { - hir::Mutability::Not => { - if is_freeze { - PointerKind::Frozen - } else { - PointerKind::Shared + let kind = if tcx.sess.opts.optimize == OptLevel::No { + // Use conservative pointer kind if not optimizing. This saves us the + // Freeze/Unpin queries, and can save time in the codegen backend (noalias + // attributes in LLVM have compile-time cost even in unoptimized builds). + PointerKind::Shared + } else { + match mt { + hir::Mutability::Not => { + if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::Frozen + } else { + PointerKind::Shared + } } - } - hir::Mutability::Mut => { - // Previously we would only emit noalias annotations for LLVM >= 6 or in - // panic=abort mode. That was deemed right, as prior versions had many bugs - // in conjunction with unwinding, but later versions didn’t seem to have - // said issues. See issue #31681. - // - // Alas, later on we encountered a case where noalias would generate wrong - // code altogether even with recent versions of LLVM in *safe* code with no - // unwinding involved. See #54462. - // - // For now, do not enable mutable_noalias by default at all, while the - // issue is being figured out. - if tcx.sess.opts.debugging_opts.mutable_noalias { - PointerKind::UniqueBorrowed - } else { - PointerKind::Shared + hir::Mutability::Mut => { + // References to self-referential structures should not be considered + // noalias, as another pointer to the structure can be obtained, that + // is not based-on the original reference. We consider all !Unpin + // types to be potentially self-referential here. + if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { + PointerKind::UniqueBorrowed + } else { + PointerKind::Shared + } } } }; @@ -2775,10 +2774,14 @@ where // and can be marked as both `readonly` and `noalias`, as // LLVM's definition of `noalias` is based solely on memory // dependencies rather than pointer equality + // + // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute + // for UniqueBorrowed arguments, so that the codegen backend can decide + // whether or not to actually emit the attribute. let no_alias = match kind { - PointerKind::Shared => false, + PointerKind::Shared | PointerKind::UniqueBorrowed => false, PointerKind::UniqueOwned => true, - PointerKind::Frozen | PointerKind::UniqueBorrowed => !is_return, + PointerKind::Frozen => !is_return, }; if no_alias { attrs.set(ArgAttribute::NoAlias); @@ -2787,6 +2790,10 @@ where if kind == PointerKind::Frozen && !is_return { attrs.set(ArgAttribute::ReadOnly); } + + if kind == PointerKind::UniqueBorrowed && !is_return { + attrs.set(ArgAttribute::NoAliasMutRef); + } } } }; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5bbf7b35d3d..e6b4739d0a2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -55,7 +55,7 @@ pub use rustc_type_ir::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; -pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, ValTree}; +pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree}; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7946d170064..3b72cc011d6 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -915,7 +915,7 @@ pub trait PrettyPrinter<'tcx>: } match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { if let Some(promoted) = promoted { p!(print_value_path(def.did, substs)); p!(write("::{:?}", promoted)); diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 48e777f7158..c170858ba85 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -217,8 +217,11 @@ macro_rules! define_callbacks { fn default() -> Self { Providers { $($name: |_, key| bug!( - "`tcx.{}({:?})` unsupported by its crate", - stringify!($name), key + "`tcx.{}({:?})` unsupported by its crate; \ + perhaps the `{}` query was never assigned a provider function", + stringify!($name), + key, + stringify!($name), ),)* } } diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 78193acc74a..ff11314d2ff 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -4,7 +4,6 @@ use crate::mir::{self, interpret}; use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; -use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; @@ -17,7 +16,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::dep_graph::DepContext; use rustc_query_system::query::QueryContext; use rustc_serialize::{ - opaque::{self, FileEncodeResult, FileEncoder}, + opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, Decodable, Decoder, Encodable, Encoder, }; use rustc_session::{CrateDisambiguator, Session}; @@ -913,12 +912,6 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId { } } -impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> { - fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error> { - Fingerprint::decode_opaque(&mut self.opaque) - } -} - impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> { RefDecodable::decode(d) @@ -1011,12 +1004,6 @@ where } } -impl<'a, 'tcx, E: OpaqueEncoder> FingerprintEncoder for CacheEncoder<'a, 'tcx, E> { - fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), E::Error> { - self.encoder.encode_fingerprint(f) - } -} - impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext where E: 'a + OpaqueEncoder, @@ -1167,6 +1154,7 @@ where emit_f32(f32); emit_char(char); emit_str(&str); + emit_raw_bytes(&[u8]); } } @@ -1180,42 +1168,6 @@ impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] { } } -// An integer that will always encode to 8 bytes. -struct IntEncodedWithFixedSize(u64); - -impl IntEncodedWithFixedSize { - pub const ENCODED_SIZE: usize = 8; -} - -impl<E: OpaqueEncoder> Encodable<E> for IntEncodedWithFixedSize { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - let start_pos = e.position(); - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - ((self.0 >> (i * 8)) as u8).encode(e)?; - } - let end_pos = e.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(()) - } -} - -impl<'a> Decodable<opaque::Decoder<'a>> for IntEncodedWithFixedSize { - fn decode(decoder: &mut opaque::Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> { - let mut value: u64 = 0; - let start_pos = decoder.position(); - - for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE { - let byte: u8 = Decodable::decode(decoder)?; - value |= (byte as u64) << (i * 8); - } - - let end_pos = decoder.position(); - assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - - Ok(IntEncodedWithFixedSize(value)) - } -} - pub fn encode_query_results<'a, 'tcx, CTX, Q>( tcx: CTX, encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 436ca4c0578..c936c30f456 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -10,6 +10,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; +use rustc_span::DUMMY_SP; use rustc_target::spec::abi; use std::iter; @@ -499,11 +500,14 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( // FIXME(oli-obk): once const generics can have generic types, this assertion // will likely get triggered. Move to `normalize_erasing_regions` at that point. - assert_eq!( - tcx.erase_regions(a.ty), - tcx.erase_regions(b.ty), - "cannot relate constants of different types" - ); + let a_ty = tcx.erase_regions(a.ty); + let b_ty = tcx.erase_regions(b.ty); + if a_ty != b_ty { + relation.tcx().sess.delay_span_bug( + DUMMY_SP, + &format!("cannot relate constants of different types: {} != {}", a_ty, b_ty), + ); + } let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env()); let a = eagerly_eval(a); @@ -527,24 +531,26 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( check_const_value_eq(relation, a_val, b_val, a, b)? } - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => { - tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => + { + tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs))) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `const_evaluatable_checked` can // be stabilized. - ( - ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted), - ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted), - ) if a_def == b_def && a_promoted == b_promoted => { + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if au.def == bu.def && au.promoted == bu.promoted => + { let substs = - relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?; + relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?; return Ok(tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: au.def, + substs, + promoted: au.promoted, + }), ty: a.ty, })); } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0ca94a9f180..2da23b331e0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1031,8 +1031,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match self { ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(did, substs, promoted) => { - ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { + def, + substs: substs.fold_with(folder), + promoted, + }) } ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) @@ -1045,7 +1049,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { match *self { ty::ConstKind::Infer(ic) => ic.visit_with(visitor), ty::ConstKind::Param(p) => p.visit_with(visitor), - ty::ConstKind::Unevaluated(_, substs, _) => substs.visit_with(visitor), + ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8edde8794ed..cff8166974a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -741,6 +741,46 @@ impl<'tcx> ty::TyS<'tcx> { } } + /// Checks whether values of this type `T` implement the `Unpin` trait. + pub fn is_unpin(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) + } + + /// Fast path helper for testing if a type is `Unpin`. + /// + /// Returning true means the type is known to be `Unpin`. Returning + /// `false` means nothing -- could be `Unpin`, might not be. + fn is_trivially_unpin(&self) -> bool { + match self.kind() { + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Never + | ty::Ref(..) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::Error(_) + | ty::FnPtr(_) => true, + ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_unpin), + ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), + ty::Adt(..) + | ty::Bound(..) + | ty::Closure(..) + | ty::Dynamic(..) + | ty::Foreign(_) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Infer(_) + | ty::Opaque(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Projection(_) => false, + } + } + /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely /// non-copy and *might* have a destructor attached; if it returns /// `false`, then `ty` definitely has no destructor (i.e., no drop glue). diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index bb7fc661d2d..c2fe5f1ef3f 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -195,8 +195,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Unevaluated(_, substs, _) => { - stack.extend(substs.iter().rev()); + ty::ConstKind::Unevaluated(ct) => { + stack.extend(ct.substs.iter().rev()); } } } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index cce1549cb29..aaa2bf4ff1b 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -316,14 +316,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let tcx = self.tcx(); let maybe_uneval = match constant.literal { ConstantKind::Ty(ct) => match ct.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { - Some((def, substs, promoted)) - } + ty::ConstKind::Unevaluated(uv) => Some(uv), _ => None, }, _ => None, }; - if let Some((def, substs, promoted)) = maybe_uneval { + if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval { if let Some(promoted) = promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, promoted: &Body<'tcx>, diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 28933493a21..c70b57e631a 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -560,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match val.val { ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { let instance = self.resolve(def, substs)?; Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 911224d8c1f..e48640e1bb9 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -646,8 +646,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { match substituted_constant.val { ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output), - ty::ConstKind::Unevaluated(def, substs, promoted) => { - match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) { + ty::ConstKind::Unevaluated(unevaluated) => { + match self.tcx.const_eval_resolve(param_env, unevaluated, None) { Ok(val) => collect_const_value(self.tcx, val, self.output), Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {} Err(ErrorHandled::TooGeneric) => span_bug!( diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 05b0e3a7dab..30e758c7fdf 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, _, Some(p)) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) // Avoid considering `T` unused when constants are of the form: // `<Self as Foo<T>>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => @@ -310,10 +310,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.visit_body(&promoted[p]); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(def, unevaluated_substs, None) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) if self.tcx.def_kind(def.did) == DefKind::AnonConst => { - self.visit_child_body(def.did, unevaluated_substs); + self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } _ => c.super_visit_with(self), diff --git a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs index 1a2d932ba19..057092b8ef5 100644 --- a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs @@ -79,7 +79,9 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) { - return; + bug!( + "Drop elaboration left behind a Drop for a type that does not need dropping" + ); } if dropped_place.is_indirect() { @@ -87,6 +89,10 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { return; } + // Drop elaboration is not precise enough to accept code like + // `src/test/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option<Vec<T>>` is + // initialized with `None` and never changed, it still emits drop glue. + // Hence we additionally check the qualifs here to allow more code to pass. if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) { // Use the span where the dropped local was declared for the error. let span = self.body.local_decls[dropped_place.local].source_info.span; diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs index 748f65cba22..36644ab3c59 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs @@ -247,7 +247,7 @@ where // Check the qualifs of the value of `const` items. if let Some(ct) = constant.literal.const_for_ty() { - if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val { + if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val { assert!(promoted.is_none()); // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def.did).is_none() { diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index cc8669d9705..7706316c965 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -491,7 +491,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let lint_only = match c.literal { ConstantKind::Ty(ct) => match ct.val { // Promoteds must lint and not error as the user didn't ask for them - ConstKind::Unevaluated(_, _, Some(_)) => true, + ConstKind::Unevaluated(ty::Unevaluated { + def: _, + substs: _, + promoted: Some(_), + }) => true, // Out of backwards compatibility we cannot report hard errors in unused // generic functions using associated constants of the generic parameters. _ => c.literal.needs_subst(), diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index e64a539c7f8..f7ea9faec47 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -26,6 +26,11 @@ pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // FIXME(#78496) + if !tcx.sess.opts.debugging_opts.unsound_mir_opts { + return; + } + if tcx.sess.mir_opt_level() < 3 { return; } diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 12fdbd6582e..b6f80763bc8 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -630,7 +630,7 @@ impl Inliner<'tcx> { caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| { match ct.literal.const_for_ty() { - Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)), + Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)), None => true, } }), diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 7db790cf32b..c5a03f3a045 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -1001,17 +1001,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { literal: tcx .mk_const(ty::Const { ty, - val: ty::ConstKind::Unevaluated( + val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, - InternalSubsts::for_item(tcx, def.did, |param, _| { + substs: InternalSubsts::for_item(tcx, def.did, |param, _| { if let ty::GenericParamDefKind::Lifetime = param.kind { tcx.lifetimes.re_erased.into() } else { tcx.mk_param_from_def(param) } }), - Some(promoted_id), - ), + promoted: Some(promoted_id), + }), }) .into(), })) diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir/src/transform/required_consts.rs index 2b518bd3a48..8b64ad65ab3 100644 --- a/compiler/rustc_mir/src/transform/required_consts.rs +++ b/compiler/rustc_mir/src/transform/required_consts.rs @@ -15,7 +15,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { if let Some(ct) = constant.literal.const_for_ty() { - if let ConstKind::Unevaluated(_, _, _) = ct.val { + if let ConstKind::Unevaluated(_) = ct.val { self.required_consts.push(*constant); } } diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index d2314a9ba15..3b074f9132f 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -422,7 +422,9 @@ impl UsedLocals<'tcx> { // A use, not a definition. self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); } else { - // A definition. Although, it still might use other locals for indexing. + // A definition. The base local itself is not visited, so this occurrence is not counted + // toward its use count. There might be other locals still, used in an indexing + // projection. self.super_projection( place.as_ref(), PlaceContext::MutatingUse(MutatingUseContext::Projection), diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 200a5fc1043..9abee283160 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -707,11 +707,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(self.tcx(), did); let lhs = mk_const(self.tcx().mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(did), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(did), substs, - None, - ), + promoted: None, + }), ty: var_ty, })); let bin = @@ -905,11 +905,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(def_id), + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), substs, - None, - ), + promoted: None, + }), ty: self.typeck_results().node_type(expr.hir_id), }), user_ty, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 6e16f803f8c..77267489a75 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -590,7 +590,7 @@ fn incremental_verify_ich<CTX, K, V: Debug>( let old_hash = tcx.dep_graph().fingerprint_of(dep_node_index); - assert!(new_hash == old_hash, "found unstable fingerprints for {:?}", dep_node,); + assert!(new_hash == old_hash, "found unstable fingerprints for {:?}: {:?}", dep_node, result); } fn force_query_with_job<C, CTX>( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 61f4c00a4ca..26858915f45 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -955,14 +955,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } return None; } - PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { + PathResult::NonModule(_) => { if no_ambiguity { assert!(import.imported_module.get().is_none()); } // The error was already reported earlier. return None; } - PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), + PathResult::Indeterminate => unreachable!(), }; let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind { diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index bbbe568f17a..51945ab435e 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -188,6 +188,7 @@ use std::collections::{BTreeMap, HashMap}; use std::io; use std::io::prelude::*; use std::mem::swap; +use std::mem::MaybeUninit; use std::num::FpCategory as Fp; use std::ops::Index; use std::str::FromStr; @@ -553,6 +554,12 @@ impl<'a> crate::Encoder for Encoder<'a> { fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where @@ -879,6 +886,12 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> { fn emit_str(&mut self, v: &str) -> EncodeResult { escape_str(self.writer, v) } + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> { + for &c in s.iter() { + self.emit_u8(c)?; + } + Ok(()) + } fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where @@ -2354,6 +2367,14 @@ impl crate::Decoder for Decoder { expect!(self.pop(), String).map(Cow::Owned) } + fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error> { + for c in s.iter_mut() { + let h = self.read_u8()?; + unsafe { *c.as_mut_ptr() = h }; + } + Ok(()) + } + fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> where F: FnOnce(&mut Decoder) -> DecodeResult<T>, diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index e439ddcdaa9..40b9522949d 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -17,6 +17,8 @@ Core encoding and decoding interfaces. #![feature(vec_spare_capacity)] #![feature(core_intrinsics)] #![feature(int_bits_const)] +#![feature(maybe_uninit_array_assume_init)] +#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_slice)] #![feature(new_uninit)] #![cfg_attr(test, feature(test))] diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 3e37fc87ce6..c171593ebdc 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -1,5 +1,5 @@ use crate::leb128::{self, max_leb128_len}; -use crate::serialize; +use crate::serialize::{self, Decoder as _, Encoder as _}; use std::borrow::Cow; use std::fs::File; use std::io::{self, Write}; @@ -30,11 +30,6 @@ impl Encoder { pub fn position(&self) -> usize { self.data.len() } - - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) { - self.data.extend_from_slice(s); - } } macro_rules! write_leb128 { @@ -154,7 +149,12 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_str(&mut self, v: &str) -> EncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()); + self.emit_raw_bytes(v.as_bytes()) + } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult { + self.data.extend_from_slice(s); Ok(()) } } @@ -208,11 +208,6 @@ impl FileEncoder { self.flushed + self.buffered } - #[inline] - pub fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { - self.write_all(s) - } - pub fn flush(&mut self) -> FileEncodeResult { // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever // offers a raw buffer access API, we can use it, and remove this. @@ -508,6 +503,11 @@ impl serialize::Encoder for FileEncoder { self.emit_usize(v.len())?; self.emit_raw_bytes(v.as_bytes()) } + + #[inline] + fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { + self.write_all(s) + } } // ----------------------------------------------------------------------------- @@ -539,26 +539,6 @@ impl<'a> Decoder<'a> { pub fn advance(&mut self, bytes: usize) { self.position += bytes; } - - #[inline] - pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> { - let start = self.position; - let end = start + s.len(); - assert!(end <= self.data.len()); - - // SAFETY: Both `src` and `dst` point to at least `s.len()` elements: - // `src` points to at least `s.len()` elements by above assert, and - // `dst` points to `s.len()` elements by derivation from `s`. - unsafe { - let src = self.data.as_ptr().add(start); - let dst = s.as_mut_ptr() as *mut u8; - ptr::copy_nonoverlapping(src, dst, s.len()); - } - - self.position = end; - - Ok(()) - } } macro_rules! read_leb128 { @@ -677,6 +657,26 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn error(&mut self, err: &str) -> Self::Error { err.to_string() } + + #[inline] + fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> { + let start = self.position; + let end = start + s.len(); + assert!(end <= self.data.len()); + + // SAFETY: Both `src` and `dst` point to at least `s.len()` elements: + // `src` points to at least `s.len()` elements by above assert, and + // `dst` points to `s.len()` elements by derivation from `s`. + unsafe { + let src = self.data.as_ptr().add(start); + let dst = s.as_mut_ptr() as *mut u8; + ptr::copy_nonoverlapping(src, dst, s.len()); + } + + self.position = end; + + Ok(()) + } } // Specializations for contiguous byte sequences follow. The default implementations for slices @@ -689,8 +689,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { impl serialize::Encodable<Encoder> for [u8] { fn encode(&self, e: &mut Encoder) -> EncodeResult { serialize::Encoder::emit_usize(e, self.len())?; - e.emit_raw_bytes(self); - Ok(()) + e.emit_raw_bytes(self) } } @@ -718,3 +717,46 @@ impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> { Ok(v) } } + +// An integer that will always encode to 8 bytes. +pub struct IntEncodedWithFixedSize(pub u64); + +impl IntEncodedWithFixedSize { + pub const ENCODED_SIZE: usize = 8; +} + +impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut Encoder) -> EncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize { + #[inline] + fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { + let _start_pos = e.position(); + e.emit_raw_bytes(&self.0.to_le_bytes())?; + let _end_pos = e.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + Ok(()) + } +} + +impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize { + #[inline] + fn decode(decoder: &mut Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> { + let mut bytes = MaybeUninit::uninit_array(); + let _start_pos = decoder.position(); + decoder.read_raw_bytes(&mut bytes)?; + let _end_pos = decoder.position(); + debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + + let value = u64::from_le_bytes(unsafe { MaybeUninit::array_assume_init(bytes) }); + Ok(IntEncodedWithFixedSize(value)) + } +} diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 47aad5b88c6..a3b02b7c34a 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -7,6 +7,7 @@ Core encoding and decoding interfaces. use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::marker::PhantomData; +use std::mem::MaybeUninit; use std::path; use std::rc::Rc; use std::sync::Arc; @@ -33,6 +34,7 @@ pub trait Encoder { fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; + fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>; // Compound types: #[inline] @@ -224,6 +226,7 @@ pub trait Decoder { fn read_f32(&mut self) -> Result<f32, Self::Error>; fn read_char(&mut self) -> Result<char, Self::Error>; fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error>; + fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error>; // Compound types: #[inline] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d9e5a186073..517051b200b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -997,8 +997,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (default: no)"), mir_opt_level: Option<usize> = (None, parse_opt_uint, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), - mutable_noalias: bool = (false, parse_bool, [TRACKED], - "emit noalias metadata for mutable references (default: no)"), + mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED], + "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"), new_llvm_pass_manager: bool = (false, parse_bool, [TRACKED], "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7bd1a21cc91..cd3dabb6795 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1081,6 +1081,7 @@ symbols! { simd_lt, simd_mul, simd_ne, + simd_neg, simd_or, simd_reduce_add_ordered, simd_reduce_add_unordered, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 0deb1186b0f..2c3f7762759 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -65,7 +65,10 @@ mod attr_impl { const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const InReg = 1 << 8; + const InReg = 1 << 5; + // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles + // in earlier versions. FIXME: Remove this distinction once possible. + const NoAliasMutRef = 1 << 6; } } } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b14b1ef00db..e2618da749f 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1112,7 +1112,7 @@ pub enum PointerKind { /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`. Frozen, - /// `&mut T`, when we know `noalias` is safe for LLVM. + /// `&mut T` which is `noalias` but not `readonly`. UniqueBorrowed, /// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns. diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6510c9464e1..0d71fc57e39 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -803,12 +803,10 @@ impl AutoTraitFinder<'tcx> { } ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match select.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty)), diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 670527fb3f0..ac987a9f7b3 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -13,7 +13,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; -use rustc_middle::mir::abstract_const::{Node, NodeId}; +use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::subst::{Subst, SubstsRef}; @@ -32,7 +32,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, -) -> Result<(), ErrorHandled> { +) -> Result<(), NotConstEvaluatable> { debug!("is_const_evaluatable({:?}, {:?})", def, substs); if infcx.tcx.features().const_evaluatable_checked { let tcx = infcx.tcx; @@ -103,29 +103,10 @@ pub fn is_const_evaluatable<'cx, 'tcx>( match failure_kind { FailureKind::MentionsInfer => { - return Err(ErrorHandled::TooGeneric); + return Err(NotConstEvaluatable::MentionsInfer); } FailureKind::MentionsParam => { - // FIXME(const_evaluatable_checked): Better error message. - let mut err = - infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant"); - let const_span = tcx.def_span(def.did); - // FIXME(const_evaluatable_checked): Update this suggestion once - // explicit const evaluatable bounds are implemented. - if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span) - { - err.span_help( - tcx.def_span(def.did), - &format!("try adding a `where` bound using this expression: `where [u8; {}]: Sized`", snippet), - ); - } else { - err.span_help( - const_span, - "consider adding a `where` bound for this expression", - ); - } - err.emit(); - return Err(ErrorHandled::Reported(ErrorReported)); + return Err(NotConstEvaluatable::MentionsParam); } FailureKind::Concrete => { // Dealt with below by the same code which handles this @@ -163,7 +144,11 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve(param_env, def, substs, None, Some(span)); + let concrete = infcx.const_eval_resolve( + param_env, + ty::Unevaluated { def, substs, promoted: None }, + Some(span), + ); if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { @@ -180,34 +165,16 @@ pub fn is_const_evaluatable<'cx, 'tcx>( debug!(?concrete, "is_const_evaluatable"); match concrete { - Err(ErrorHandled::TooGeneric) if !substs.has_infer_types_or_consts() => { - // FIXME(const_evaluatable_checked): We really should move - // emitting this error message to fulfill instead. For - // now this is easier. - // - // This is not a problem without `const_evaluatable_checked` as - // all `ConstEvaluatable` predicates have to be fulfilled for compilation - // to succeed. - // - // @lcnr: We already emit an error for things like - // `fn test<const N: usize>() -> [0 - N]` eagerly here, - // so until we fix this I don't really care. - - let mut err = infcx - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - // - // Note that with `feature(const_evaluatable_checked)` this case should not - // be reachable. - err.note("this may fail depending on what value the parameter takes"); - err.emit(); - Err(ErrorHandled::Reported(ErrorReported)) + Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() { + true => NotConstEvaluatable::MentionsInfer, + false => NotConstEvaluatable::MentionsParam, + }), + Err(ErrorHandled::Linted) => { + infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); + Err(NotConstEvaluatable::Error(ErrorReported)) } - c => c.map(drop), + Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), + Ok(_) => Ok(()), } } @@ -239,7 +206,9 @@ impl AbstractConst<'tcx> { ct: &ty::Const<'tcx>, ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(def, substs, None) => AbstractConst::new(tcx, def, substs), + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => { + AbstractConst::new(tcx, def, substs) + } ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } @@ -532,22 +501,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { if let Some(next) = self.build_terminator(block.terminator())? { block = &self.body.basic_blocks()[next]; } else { - assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + break; + } + } + + assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); + for n in self.nodes.iter() { + if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. - assert!(!self.nodes.iter().any(|n| matches!( - n.node, - Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ }) - ))); - - self.nodes[self.locals[mir::RETURN_PLACE]].used = true; - if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { - self.error(Some(unused.span), "dead code")?; - } - - return Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))); + assert_eq!(ct.promoted, None); } } + + self.nodes[self.locals[mir::RETURN_PLACE]].used = true; + if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { + self.error(Some(unused.span), "dead code")?; + } + + Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) } } @@ -673,10 +645,16 @@ pub(super) fn try_unify<'tcx>( // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This // means that we only allow inference variables if they are equal. (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val, - ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) => a_def == b_def && a_substs == b_substs, + // We expand generic anonymous constants at the start of this function, so this + // branch should only be taking when dealing with associated constants, at + // which point directly comparing them seems like the desired behavior. + // + // FIXME(const_evaluatable_checked): This isn't actually the case. + // We also take this branch for concrete anonymous constants and + // expand generic anonymous constants with concrete substs. + (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => { + a_uv == b_uv + } // FIXME(const_evaluatable_checked): We may want to either actually try // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like // this, for now we just return false here. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index a3faf4cb7d4..060e4e36dfe 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2,10 +2,10 @@ pub mod on_unimplemented; pub mod suggestions; use super::{ - ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, - OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, - PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, + EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, + OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, + SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -17,7 +17,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ @@ -738,24 +738,59 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } - ConstEvalFailure(ErrorHandled::TooGeneric) => { - bug!("too generic should have been handled in `is_const_evaluatable`"); + + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { + bug!( + "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" + ) + } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { + if !self.tcx.features().const_evaluatable_checked { + let mut err = self.tcx.sess.struct_span_err( + span, + "constant expression depends on a generic parameter", + ); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + // + // Note that with `feature(const_evaluatable_checked)` this case should not + // be reachable. + err.note("this may fail depending on what value the parameter takes"); + err.emit(); + return; + } + + match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::ConstEvaluatable(def, _) => { + let mut err = + self.tcx.sess.struct_span_err(span, "unconstrained generic constant"); + let const_span = self.tcx.def_span(def.did); + match self.tcx.sess.source_map().span_to_snippet(const_span) { + Ok(snippet) => err.help(&format!( + "try adding a `where` bound using this expression: `where [(); {}]:`", + snippet + )), + _ => err.help("consider adding a `where` bound using this expression"), + }; + err + } + _ => { + span_bug!( + span, + "unexpected non-ConstEvaluatable predicate, this should not be reachable" + ) + } + } } + // Already reported in the query. - ConstEvalFailure(ErrorHandled::Reported(ErrorReported)) => { + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(ErrorReported)) => { // FIXME(eddyb) remove this once `ErrorReported` becomes a proof token. self.tcx.sess.delay_span_bug(span, "`ErrorReported` without an error"); return; } - // Already reported in the query, but only as a lint. - // This shouldn't actually happen for constants used in types, modulo - // bugs. The `delay_span_bug` here ensures it won't be ignored. - ConstEvalFailure(ErrorHandled::Linted) => { - self.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint"); - return; - } - Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7d451fc2341..79f65669479 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -3,7 +3,8 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_infer::traits::{TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::subst::SubstsRef; @@ -18,7 +19,7 @@ use super::wf; use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; -use super::{ConstEvalFailure, Unimplemented}; +use super::Unimplemented; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; @@ -498,14 +499,19 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { obligation.cause.span, ) { Ok(()) => ProcessResult::Changed(vec![]), - Err(ErrorHandled::TooGeneric) => { + Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); pending_obligation.stalled_on.extend( substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); ProcessResult::Unchanged } - Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))), + Err( + e @ NotConstEvaluatable::MentionsParam + | e @ NotConstEvaluatable::Error(_), + ) => ProcessResult::Error(CodeSelectionError( + SelectionError::NotConstEvaluatable(e), + )), } } @@ -516,15 +522,13 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { // if the constants depend on generic parameters. // // Let's just see where this breaks :shrug: - if let ( - ty::ConstKind::Unevaluated(a_def, a_substs, None), - ty::ConstKind::Unevaluated(b_def, b_substs, None), - ) = (c1.val, c2.val) + if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = + (c1.val, c2.val) { if self .selcx .tcx() - .try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) + .try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs))) { return ProcessResult::Changed(vec![]); } @@ -534,18 +538,17 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let stalled_on = &mut pending_obligation.stalled_on; let mut evaluate = |c: &'tcx Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { match self.selcx.infcx().const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) { Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)), Err(ErrorHandled::TooGeneric) => { stalled_on.extend( - substs + unevaluated + .substs .iter() .filter_map(TyOrConstInferVar::maybe_from_generic_arg), ); @@ -576,11 +579,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } } (Err(ErrorHandled::Reported(ErrorReported)), _) - | (_, Err(ErrorHandled::Reported(ErrorReported))) => { - ProcessResult::Error(CodeSelectionError(ConstEvalFailure( - ErrorHandled::Reported(ErrorReported), - ))) - } + | (_, Err(ErrorHandled::Reported(ErrorReported))) => ProcessResult::Error( + CodeSelectionError(SelectionError::NotConstEvaluatable( + NotConstEvaluatable::Error(ErrorReported), + )), + ), (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { span_bug!( obligation.cause.span(self.selcx.tcx()), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 45b5aff40a6..bc0f0d6dea5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -34,6 +34,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::Constness; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -547,7 +548,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.span, ) { Ok(()) => Ok(EvaluatedToOk), - Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig), + Err(NotConstEvaluatable::MentionsParam) => Ok(EvaluatedToErr), Err(_) => Ok(EvaluatedToErr), } } @@ -556,13 +558,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); let evaluate = |c: &'tcx ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { + if let ty::ConstKind::Unevaluated(unevaluated) = c.val { self.infcx .const_eval_resolve( obligation.param_env, - def, - substs, - promoted, + unevaluated, Some(obligation.cause.span), ) .map(|val| ty::Const::from_value(self.tcx(), val, c.ty)) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e6ef9b137d8..aee128dec7d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { GenericArgKind::Const(constant) => { match constant.val { - ty::ConstKind::Unevaluated(def, substs, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { assert!(promoted.is_none()); let obligations = self.nominal_obligations(def.did, substs); diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index 24ba0717866..cedc84d97c2 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -18,6 +18,10 @@ fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>> is_item_raw(tcx, query, LangItem::Freeze) } +fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + is_item_raw(tcx, query, LangItem::Unpin) +} + fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -37,5 +41,11 @@ fn is_item_raw<'tcx>( } pub(crate) fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { is_copy_raw, is_sized_raw, is_freeze_raw, ..*providers }; + *providers = ty::query::Providers { + is_copy_raw, + is_sized_raw, + is_freeze_raw, + is_unpin_raw, + ..*providers + }; } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index dedf96863ea..990ed5abdbf 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -398,6 +398,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fpow | sym::simd_saturating_add | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), + sym::simd_neg => (1, vec![param(0)], param(0)), sym::simd_fsqrt | sym::simd_fsin | sym::simd_fcos diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 42d7f4c988d..3006cabc632 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -742,9 +742,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("assemble_inherent_impl_probe {:?}", impl_def_id); - let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let impl_ty = impl_ty.subst(self.tcx, impl_substs); - for item in self.impl_or_trait_item(impl_def_id) { if !self.has_applicable_self(&item) { // No receiver declared. Not a candidate. @@ -752,6 +749,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { continue; } + let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); + let impl_ty = impl_ty.subst(self.tcx, impl_substs); + // Determine the receiver type that the method itself expects. let xform_tys = self.xform_self_ty(&item, impl_ty, impl_substs); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e5136355ca9..162fccc6020 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2212,10 +2212,11 @@ fn const_evaluatable_predicates_of<'tcx>( fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { let def_id = self.tcx.hir().local_def_id(c.hir_id); let ct = ty::Const::from_anon_const(self.tcx, def_id); - if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { + if let ty::ConstKind::Unevaluated(uv) = ct.val { + assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx), + ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx), span, )); } diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index d95b5b7f17f..4f97c95bcb9 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "alloc" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust core allocation and collections library" autotests = false autobenches = false edition = "2018" diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 73eb353f6e7..7a098219ce4 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -548,6 +548,22 @@ fn bench_in_place_zip_iter_mut(b: &mut Bencher) { black_box(data); } +pub fn vec_cast<T, U>(input: Vec<T>) -> Vec<U> { + input.into_iter().map(|e| unsafe { std::mem::transmute_copy(&e) }).collect() +} + +#[bench] +fn bench_transmute(b: &mut Bencher) { + let mut vec = vec![10u32; 100]; + b.bytes = 800; // 2 casts x 4 bytes x 100 + b.iter(|| { + let v = std::mem::take(&mut vec); + let v = black_box(vec_cast::<u32, i32>(v)); + let v = black_box(vec_cast::<i32, u32>(v)); + vec = v; + }); +} + #[derive(Clone)] struct Droppable(usize); diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 465b058cd98..1c635dd4f27 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use super::VecDeque; @@ -36,6 +36,22 @@ impl<T> Iterator for IntoIter<T> { let len = self.inner.len(); (len, Some(len)) } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even + // multiple repeated reads of the same index would be safe and the + // values are !Drop, thus won't suffer from double drops. + unsafe { + let idx = self.inner.wrap_add(self.inner.tail, idx); + self.inner.buffer_read(idx) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -55,3 +71,17 @@ impl<T> ExactSizeIterator for IntoIter<T> { #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for IntoIter<T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<T> TrustedLen for IntoIter<T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +// T: Copy as approximation for !Drop since get_unchecked does not update the pointers +// and thus we can't implement drop-handling +unsafe impl<T> TrustedRandomAccess for IntoIter<T> +where + T: Copy, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index ad31b991cb6..e4cfb3acdfd 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use core::ops::Try; use super::{count, wrap_index, RingSlices}; @@ -101,6 +101,19 @@ impl<'a, T> Iterator for Iter<'a, T> { fn last(mut self) -> Option<&'a T> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + self.ring.get_unchecked(idx) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -157,3 +170,12 @@ impl<T> ExactSizeIterator for Iter<'_, T> { #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for Iter<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<T> TrustedLen for Iter<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<T> TrustedRandomAccess for Iter<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 3d0c3094e26..9493676e66b 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -1,5 +1,5 @@ use core::fmt; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use core::marker::PhantomData; use super::{count, wrap_index, RingSlices}; @@ -87,6 +87,19 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn last(mut self) -> Option<&'a mut T> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + unsafe { + let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len()); + &mut *self.ring.get_unchecked_mut(idx) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -126,3 +139,12 @@ impl<T> ExactSizeIterator for IterMut<'_, T> { #[stable(feature = "fused", since = "1.26.0")] impl<T> FusedIterator for IterMut<'_, T> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<T> TrustedLen for IterMut<'_, T> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f7cefdce278..d3e70991ad5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -58,7 +58,7 @@ mod tests; const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 -const MAXIMUM_ZST_CAPACITY: usize = 1 << (core::mem::size_of::<usize>() * 8 - 1); // Largest possible power of two +const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two /// A double-ended queue implemented with a growable ring buffer. /// @@ -2783,27 +2783,26 @@ impl<T> From<Vec<T>> for VecDeque<T> { /// This avoids reallocating where possible, but the conditions for that are /// strict, and subject to change, and so shouldn't be relied upon unless the /// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated. - fn from(other: Vec<T>) -> Self { - unsafe { - let mut other = ManuallyDrop::new(other); - let other_buf = other.as_mut_ptr(); - let mut buf = RawVec::from_raw_parts(other_buf, other.capacity()); - let len = other.len(); - - // We need to extend the buf if it's not a power of two, too small - // or doesn't have at least one free space. - // We check if `T` is a ZST in the first condition, - // because `usize::MAX` (the capacity returned by `capacity()` for ZST) - // is not a power of two and thus it'll always try - // to reserve more memory which will panic for ZST (rust-lang/rust#78532) - if (!buf.capacity().is_power_of_two() && mem::size_of::<T>() != 0) - || (buf.capacity() < (MINIMUM_CAPACITY + 1)) - || (buf.capacity() == len) - { - let cap = cmp::max(buf.capacity() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); - buf.reserve_exact(len, cap - len); + fn from(mut other: Vec<T>) -> Self { + let len = other.len(); + if mem::size_of::<T>() == 0 { + // There's no actual allocation for ZSTs to worry about capacity, + // but `VecDeque` can't handle as much length as `Vec`. + assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow"); + } else { + // We need to resize if the capacity is not a power of two, too small or + // doesn't have at least one free space. We do this while it's still in + // the `Vec` so the items will drop on panic. + let min_cap = cmp::max(MINIMUM_CAPACITY, len) + 1; + let cap = cmp::max(min_cap, other.capacity()).next_power_of_two(); + if other.capacity() != cap { + other.reserve_exact(cap - len); } + } + unsafe { + let (other_buf, len, capacity) = other.into_raw_parts(); + let buf = RawVec::from_raw_parts(other_buf, capacity); VecDeque { tail: 0, head: len, buf } } } diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 87e06fa394d..6116cfe1d01 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -457,6 +457,21 @@ fn test_from_vec() { assert!(vd.into_iter().eq(vec)); } } + + let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY - 1]); + let vd = VecDeque::from(vec.clone()); + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); +} + +#[test] +#[should_panic = "capacity overflow"] +fn test_from_vec_zst_overflow() { + use crate::vec::Vec; + let vec = Vec::from([(); MAXIMUM_ZST_CAPACITY]); + let vd = VecDeque::from(vec.clone()); // no room for +1 + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); } #[test] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 019b17a5945..f4ec4a36ffd 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -360,7 +360,7 @@ impl String { /// let s = String::new(); /// ``` #[inline] - #[rustc_const_stable(feature = "const_string_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> String { String { vec: Vec::new() } @@ -1289,37 +1289,44 @@ impl String { where F: FnMut(char) -> bool, { - let len = self.len(); - let mut del_bytes = 0; - let mut idx = 0; + struct SetLenOnDrop<'a> { + s: &'a mut String, + idx: usize, + del_bytes: usize, + } - unsafe { - self.vec.set_len(0); + impl<'a> Drop for SetLenOnDrop<'a> { + fn drop(&mut self) { + let new_len = self.idx - self.del_bytes; + debug_assert!(new_len <= self.s.len()); + unsafe { self.s.vec.set_len(new_len) }; + } } - while idx < len { - let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap() }; + let len = self.len(); + let mut guard = SetLenOnDrop { s: self, idx: 0, del_bytes: 0 }; + + while guard.idx < len { + let ch = unsafe { guard.s.get_unchecked(guard.idx..len).chars().next().unwrap() }; let ch_len = ch.len_utf8(); if !f(ch) { - del_bytes += ch_len; - } else if del_bytes > 0 { + guard.del_bytes += ch_len; + } else if guard.del_bytes > 0 { unsafe { ptr::copy( - self.vec.as_ptr().add(idx), - self.vec.as_mut_ptr().add(idx - del_bytes), + guard.s.vec.as_ptr().add(guard.idx), + guard.s.vec.as_mut_ptr().add(guard.idx - guard.del_bytes), ch_len, ); } } // Point idx to the next char - idx += ch_len; + guard.idx += ch_len; } - unsafe { - self.vec.set_len(len - del_bytes); - } + drop(guard); } /// Inserts a character into this `String` at a byte position. diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index 8c0e95559fa..50882fc1767 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -1,4 +1,4 @@ -use core::iter::{InPlaceIterable, SourceIter}; +use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccess}; use core::mem::{self, ManuallyDrop}; use core::ptr::{self}; @@ -52,16 +52,7 @@ where ) }; - // use try-fold since - // - it vectorizes better for some iterator adapters - // - unlike most internal iteration methods, it only takes a &mut self - // - it lets us thread the write pointer through its innards and get it back in the end - let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; - let sink = iterator - .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) - .unwrap(); - // iteration succeeded, don't drop head - let dst = ManuallyDrop::new(sink).dst; + let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end); let src = unsafe { iterator.as_inner().as_into_iter() }; // check if SourceIter contract was upheld @@ -72,7 +63,7 @@ where // then the source pointer will stay in its initial position and we can't use it as reference if src.ptr != src_ptr { debug_assert!( - dst as *const _ <= src.ptr, + unsafe { dst_buf.add(len) as *const _ } <= src.ptr, "InPlaceIterable contract violation, write pointer advanced beyond read pointer" ); } @@ -82,10 +73,7 @@ where // but prevent drop of the allocation itself once IntoIter goes out of scope src.forget_allocation(); - let vec = unsafe { - let len = dst.offset_from(dst_buf) as usize; - Vec::from_raw_parts(dst_buf, len, cap) - }; + let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) }; vec } @@ -106,3 +94,52 @@ fn write_in_place_with_drop<T>( Ok(sink) } } + +/// Helper trait to hold specialized implementations of the in-place iterate-collect loop +trait SpecInPlaceCollect<T, I>: Iterator<Item = T> { + /// Collects an iterator (`self`) into the destination buffer (`dst`) and returns the number of items + /// collected. `end` is the last writable element of the allocation and used for bounds checks. + fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize; +} + +impl<T, I> SpecInPlaceCollect<T, I> for I +where + I: Iterator<Item = T>, +{ + #[inline] + default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = + self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).unwrap(); + // iteration succeeded, don't drop head + unsafe { ManuallyDrop::new(sink).dst.offset_from(dst_buf) as usize } + } +} + +impl<T, I> SpecInPlaceCollect<T, I> for I +where + I: Iterator<Item = T> + TrustedRandomAccess, +{ + #[inline] + fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize { + let len = self.size(); + let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + for i in 0..len { + // Safety: InplaceIterable contract guarantees that for every element we read + // one slot in the underlying storage will have been freed up and we can immediately + // write back the result. + unsafe { + let dst = dst_buf.offset(i as isize); + debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); + ptr::write(dst, self.__iterator_get_unchecked(i)); + drop_guard.dst = dst.add(1); + } + } + mem::forget(drop_guard); + len + } +} diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index c1596012eac..4a7dbb91822 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "core" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "The Rust Core Library" autotests = false autobenches = false edition = "2018" diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 8b95b70396b..0e7667dd89e 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -93,7 +93,7 @@ impl Layout { /// This function is unsafe as it does not verify the preconditions from /// [`Layout::from_size_align`]. #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")] + #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { // SAFETY: the caller must ensure that `align` is greater than zero. diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 4472fba26b9..f82454addd0 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -2,7 +2,7 @@ use crate::{ fmt, - iter::{ExactSizeIterator, FusedIterator, TrustedLen}, + iter::{ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess}, mem::{self, MaybeUninit}, ops::Range, ptr, @@ -130,6 +130,18 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> { fn last(mut self) -> Option<Self::Item> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: Callers are only allowed to pass an index that is in bounds + // Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even + // multiple repeated reads of the same index would be safe and the + // values aree !Drop, thus won't suffer from double drops. + unsafe { self.data.get_unchecked(self.alive.start + idx).assume_init_read() } + } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] @@ -184,6 +196,17 @@ impl<T, const N: usize> FusedIterator for IntoIter<T, N> {} #[stable(feature = "array_value_iter_impls", since = "1.40.0")] unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {} +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +// T: Copy as approximation for !Drop since get_unchecked does not update the pointers +// and thus we can't implement drop-handling +unsafe impl<T, const N: usize> TrustedRandomAccess for IntoIter<T, N> +where + T: Copy, +{ + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl<T: Clone, const N: usize> Clone for IntoIter<T, N> { fn clone(&self) -> Self { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2fbbeb35e1d..fa21a40e169 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -325,7 +325,7 @@ impl<T> Cell<T> { /// let c = Cell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_cell_new", since = "1.24.0")] #[inline] pub const fn new(value: T) -> Cell<T> { Cell { value: UnsafeCell::new(value) } @@ -655,7 +655,7 @@ impl<T> RefCell<T> { /// let c = RefCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_refcell_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")] #[inline] pub const fn new(value: T) -> RefCell<T> { RefCell { value: UnsafeCell::new(value), borrow: Cell::new(UNUSED) } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index b3e1becf570..87a3d375a69 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -18,7 +18,7 @@ impl char { /// /// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value /// [Code Point]: http://www.unicode.org/glossary/#code_point - #[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const MAX: char = '\u{10ffff}'; /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a @@ -26,7 +26,7 @@ impl char { /// /// It can occur, for example, when giving ill-formed UTF-8 bytes to /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy). - #[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of @@ -39,7 +39,7 @@ impl char { /// /// The version numbering scheme is explained in /// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). - #[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION; /// Creates an iterator over the UTF-16 encoded code points in `iter`, @@ -88,7 +88,7 @@ impl char { /// "𝄞mus�ic�" /// ); /// ``` - #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] #[inline] pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> { super::decode::decode_utf16(iter) @@ -136,7 +136,7 @@ impl char { /// /// assert_eq!(None, c); /// ``` - #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] #[inline] pub fn from_u32(i: u32) -> Option<char> { super::convert::from_u32(i) @@ -177,7 +177,7 @@ impl char { /// /// assert_eq!('❤', c); /// ``` - #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] #[inline] pub unsafe fn from_u32_unchecked(i: u32) -> char { // SAFETY: the safety contract must be upheld by the caller. @@ -233,7 +233,7 @@ impl char { /// // this panics /// char::from_digit(1, 37); /// ``` - #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")] + #[stable(feature = "assoc_char_funcs", since = "1.52.0")] #[inline] pub fn from_digit(num: u32, radix: u32) -> Option<char> { super::convert::from_digit(num, radix) diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index f8d684fcdda..0337892b9e8 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -13,7 +13,8 @@ use crate::ops::Try; #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Filter<I, P> { - iter: I, + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) iter: I, predicate: P, } impl<I, P> Filter<I, P> { diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 2d997cfe509..2a4b7efd5e6 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -57,7 +57,8 @@ use crate::ops::Try; #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Map<I, F> { - iter: I, + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) iter: I, f: F, } diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index cc80e06decd..4b293c596e7 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -3,7 +3,7 @@ use crate::convert::TryFrom; use crate::mem; use crate::ops::{self, Try}; -use super::{FusedIterator, TrustedLen}; +use super::{FusedIterator, TrustedLen, TrustedRandomAccess}; /// Objects that have a notion of *successor* and *predecessor* operations. /// @@ -493,6 +493,18 @@ macro_rules! range_exact_iter_impl { )*) } +/// Safety: This macro must only be used on types that are `Copy` and result in ranges +/// which have an exact `size_hint()` where the upper bound must not be `None`. +macro_rules! unsafe_range_trusted_random_access_impl { + ($($t:ty)*) => ($( + #[doc(hidden)] + #[unstable(feature = "trusted_random_access", issue = "none")] + unsafe impl TrustedRandomAccess for ops::Range<$t> { + const MAY_HAVE_SIDE_EFFECT: bool = false; + } + )*) +} + macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "inclusive_range", since = "1.26.0")] @@ -553,6 +565,18 @@ impl<A: Step> Iterator for ops::Range<A> { fn max(mut self) -> Option<A> { self.next_back() } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // that is in bounds. + // Additionally Self: TrustedRandomAccess is only implemented for Copy types + // which means even repeated reads of the same index would be safe. + unsafe { Step::forward_unchecked(self.start.clone(), idx) } + } } // These macros generate `ExactSizeIterator` impls for various range types. @@ -574,6 +598,23 @@ range_exact_iter_impl! { u32 i32 } + +unsafe_range_trusted_random_access_impl! { + usize u8 u16 + isize i8 i16 +} + +#[cfg(target_pointer_width = "32")] +unsafe_range_trusted_random_access_impl! { + u32 i32 +} + +#[cfg(target_pointer_width = "64")] +unsafe_range_trusted_random_access_impl! { + u32 i32 + u64 i64 +} + range_incl_exact_iter_impl! { u8 i8 diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a07750f4ad1..46e1a3a4aa2 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1228,7 +1228,11 @@ pub trait Iterator { /// Creates an iterator that skips the first `n` elements. /// - /// After they have been consumed, the rest of the elements are yielded. + /// `skip(n)` skips elements until `n` elements are skipped or the end of the + /// iterator is reached (whichever happens first). After that, all the remaining + /// elements are yielded. In particular, if the original iterator is too short, + /// then the returned iterator is empty. + /// /// Rather than overriding this method directly, instead override the `nth` method. /// /// # Examples @@ -1252,7 +1256,14 @@ pub trait Iterator { Skip::new(self, n) } - /// Creates an iterator that yields its first `n` elements. + /// Creates an iterator that yields the first `n` elements, or fewer + /// if the underlying iterator ends sooner. + /// + /// `take(n)` yields elements until `n` elements are yielded or the end of + /// the iterator is reached (whichever happens first). + /// The returned iterator is a prefix of length `n` if the original iterator + /// contains at least `n` elements, otherwise it contains all of the + /// (fewer than `n`) elements of the original iterator. /// /// # Examples /// diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 6e502426df9..5127a16bbfd 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -9,11 +9,15 @@ tests. `panic!` is closely tied with the `unwrap` method of both [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set to [`None`] or [`Err`] variants. -This macro is used to inject panic into a Rust thread, causing the thread to -panic entirely. This macro panics with a string and uses the [`format!`] syntax -for building the message. - -Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type, +When using `panic!()` you can specify a string payload, that is built using +the [`format!`] syntax. That payload is used when injecting the panic into +the calling Rust thread, causing the thread to panic entirely. + +The behavior of the default `std` hook, i.e. the code that runs directly +after the panic is invoked, is to print the message payload to +`stderr` along with the file/line/column information of the `panic!()` +call. You can override the panic hook using [`std::panic::set_hook()`]. +Inside the hook a panic can be accessed as a `&dyn Any + Send`, which contains either a `&str` or `String` for regular `panic!()` invocations. To panic with a value of another other type, [`panic_any`] can be used. @@ -26,6 +30,7 @@ See also the macro [`compile_error!`], for raising errors during compilation. [ounwrap]: Option::unwrap [runwrap]: Result::unwrap +[`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html [`panic_any`]: ../std/panic/fn.panic_any.html [`Box`]: ../std/boxed/struct.Box.html [`Any`]: crate::any::Any diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 37e8d65db6a..446d72f1d32 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -297,7 +297,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_size_of", since = "1.32.0")] +#[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] pub const fn size_of<T>() -> usize { intrinsics::size_of::<T>() } @@ -440,7 +440,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_align_of", since = "1.32.0")] +#[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] pub const fn align_of<T>() -> usize { intrinsics::min_align_of::<T>() } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index ce9dca39d0e..79737b48d79 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1589,11 +1589,11 @@ macro_rules! int_impl { /// Calculates the quotient of Euclidean division of `self` by `rhs`. /// - /// This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, - /// with `0 <= self.rem_euclid(rhs) < rhs`. + /// This computes the integer `q` such that `self = q * rhs + r`, with + /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`. /// - /// In other words, the result is `self / rhs` rounded to the integer `n` - /// such that `self >= n * rhs`. + /// In other words, the result is `self / rhs` rounded to the integer `q` + /// such that `self >= q * rhs`. /// If `self > 0`, this is equal to round towards zero (the default in Rust); /// if `self < 0`, this is equal to round towards +/- infinity. /// diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 92090d8e6fc..a0577b287ce 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -456,9 +456,13 @@ pub trait Div<Rhs = Self> { } macro_rules! div_impl_integer { - ($($t:ty)*) => ($( + ($(($($t:ty)*) => $panic:expr),*) => ($($( /// This operation rounds towards zero, truncating any /// fractional part of the exact result. + /// + /// # Panics + /// + #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] impl Div for $t { type Output = $t; @@ -468,10 +472,13 @@ macro_rules! div_impl_integer { } forward_ref_binop! { impl Div, div for $t, $t } - )*) + )*)*) } -div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +div_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or the division results in overflow." +} macro_rules! div_impl_float { ($($t:ty)*) => ($( @@ -549,9 +556,13 @@ pub trait Rem<Rhs = Self> { } macro_rules! rem_impl_integer { - ($($t:ty)*) => ($( + ($(($($t:ty)*) => $panic:expr),*) => ($($( /// This operation satisfies `n % d == n - (n / d) * d`. The /// result has the same sign as the left operand. + /// + /// # Panics + /// + #[doc = $panic] #[stable(feature = "rust1", since = "1.0.0")] impl Rem for $t { type Output = $t; @@ -561,10 +572,13 @@ macro_rules! rem_impl_integer { } forward_ref_binop! { impl Rem, rem for $t, $t } - )*) + )*)*) } -rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +rem_impl_integer! { + (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.", + (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or if `self / other` results in overflow." +} macro_rules! rem_impl_float { ($($t:ty)*) => ($( diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 3a27f01444b..7e4f8d570a7 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -205,7 +205,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] pub const fn null<T>() -> *const T { 0 as *const T } @@ -223,7 +223,7 @@ pub const fn null<T>() -> *const T { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] pub const fn null_mut<T>() -> *mut T { 0 as *mut T } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 8d533cd6be1..83b88ffd916 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -72,7 +72,7 @@ impl<T: Sized> NonNull<T> { /// sentinel value. Types that lazily allocate must track initialization by /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")] #[inline] pub const fn dangling() -> Self { // SAFETY: mem::align_of() returns a non-zero usize which is then casted @@ -110,7 +110,7 @@ impl<T: Sized> NonNull<T> { /// [the module documentation]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit<T> { + pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit<T> { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.cast().as_ptr() } @@ -142,7 +142,7 @@ impl<T: Sized> NonNull<T> { /// [the module documentation]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit<T> { + pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit<T> { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &mut *self.cast().as_ptr() } @@ -156,7 +156,7 @@ impl<T: ?Sized> NonNull<T> { /// /// `ptr` must be non-null. #[stable(feature = "nonnull", since = "1.25.0")] - #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")] #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. @@ -244,7 +244,7 @@ impl<T: ?Sized> NonNull<T> { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - pub unsafe fn as_ref(&self) -> &T { + pub unsafe fn as_ref<'a>(&self) -> &'a T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.as_ptr() } @@ -280,7 +280,7 @@ impl<T: ?Sized> NonNull<T> { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { + pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. unsafe { &mut *self.as_ptr() } @@ -288,7 +288,7 @@ impl<T: ?Sized> NonNull<T> { /// Casts to a pointer of another type. #[stable(feature = "nonnull_cast", since = "1.27.0")] - #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.32.0")] + #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")] #[inline] pub const fn cast<U>(self) -> NonNull<U> { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null @@ -427,7 +427,7 @@ impl<T> NonNull<[T]> { /// [valid]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit<T>] { + pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit<T>] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } } @@ -488,7 +488,7 @@ impl<T> NonNull<[T]> { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit<T>] { + pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit<T>] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 796301c76b6..1ee662c6c8e 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -286,7 +286,6 @@ impl<'a, T> IterMut<'a, T> { /// Basic usage: /// /// ``` - /// # #![feature(slice_iter_mut_as_slice)] /// let mut slice: &mut [usize] = &mut [1, 2, 3]; /// /// // First, we get the iterator: @@ -299,12 +298,19 @@ impl<'a, T> IterMut<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// assert_eq!(iter.as_slice(), &[2, 3]); /// ``` - #[unstable(feature = "slice_iter_mut_as_slice", reason = "recently added", issue = "58957")] + #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] pub fn as_slice(&self) -> &[T] { self.make_slice() } } +#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] +impl<T> AsRef<[T]> for IterMut<'_, T> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}} /// An internal abstraction over the splitting iterators, so that @@ -335,9 +341,11 @@ pub struct Split<'a, T: 'a, P> where P: FnMut(&T) -> bool, { - v: &'a [T], + // Used for `SplitWhitespace` and `SplitAsciiWhitespace` `as_str` methods + pub(crate) v: &'a [T], pred: P, - finished: bool, + // Used for `SplitAsciiWhitespace` `as_str` method + pub(crate) finished: bool, } impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 417a106b99a..1e9e9c24a45 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -94,7 +94,7 @@ impl<T> [T] { /// ``` #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] + #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) #[rustc_allow_const_fn_unstable(const_fn_union)] @@ -127,7 +127,7 @@ impl<T> [T] { /// assert!(!a.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.32.0")] + #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")] #[inline] pub const fn is_empty(&self) -> bool { self.len() == 0 diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 0c9307a6d2f..4eac017f915 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1200,6 +1200,30 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for SplitWhitespace<'_> {} +impl<'a> SplitWhitespace<'a> { + /// Returns remainder of the splitted string + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_whitespace_as_str)] + /// + /// let mut split = "Mary had a little lamb".split_whitespace(); + /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// + /// split.next(); + /// assert_eq!(split.as_str(), "had a little lamb"); + /// + /// split.by_ref().for_each(drop); + /// assert_eq!(split.as_str(), ""); + /// ``` + #[inline] + #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] + pub fn as_str(&self) -> &'a str { + self.inner.iter.as_str() + } +} + #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] impl<'a> Iterator for SplitAsciiWhitespace<'a> { type Item = &'a str; @@ -1231,6 +1255,35 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] impl FusedIterator for SplitAsciiWhitespace<'_> {} +impl<'a> SplitAsciiWhitespace<'a> { + /// Returns remainder of the splitted string + /// + /// # Examples + /// + /// ``` + /// #![feature(str_split_whitespace_as_str)] + /// + /// let mut split = "Mary had a little lamb".split_ascii_whitespace(); + /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// + /// split.next(); + /// assert_eq!(split.as_str(), "had a little lamb"); + /// + /// split.by_ref().for_each(drop); + /// assert_eq!(split.as_str(), ""); + /// ``` + #[inline] + #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] + pub fn as_str(&self) -> &'a str { + if self.inner.iter.iter.finished { + return ""; + } + + // SAFETY: Slice is created from str. + unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) } + } +} + #[stable(feature = "split_inclusive", since = "1.51.0")] impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { type Item = &'a str; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 50ccc2a2eab..03ed301eacf 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -66,7 +66,7 @@ pub use iter::{EscapeDebug, EscapeDefault, EscapeUnicode}; pub use iter::SplitAsciiWhitespace; #[stable(feature = "split_inclusive", since = "1.51.0")] -use iter::SplitInclusive; +pub use iter::SplitInclusive; #[unstable(feature = "str_internals", issue = "none")] pub use validations::next_code_point; @@ -140,7 +140,7 @@ impl str { /// ``` #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_str_len", since = "1.32.0")] + #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] #[inline] pub const fn len(&self) -> usize { self.as_bytes().len() @@ -161,7 +161,7 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_str_is_empty", since = "1.32.0")] + #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -217,7 +217,7 @@ impl str { /// assert_eq!(b"bors", bytes); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")] + #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] #[inline(always)] #[allow(unused_attributes)] #[rustc_allow_const_fn_unstable(const_fn_transmute)] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index ca39224602e..bf70b28579c 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -283,7 +283,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] pub const fn new(v: bool) -> AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } @@ -883,7 +883,7 @@ impl<T> AtomicPtr<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] pub const fn new(p: *mut T) -> AtomicPtr<T> { AtomicPtr { p: UnsafeCell::new(p) } } @@ -2276,7 +2276,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "isize", "", @@ -2296,7 +2296,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "usize", "", diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index b15919fad75..caa89aa30d0 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "panic_abort" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Implementation of Rust panics via process aborts" edition = "2018" [lib] diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index d27ba987641..533f059a85e 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -2,6 +2,9 @@ authors = ["The Rust Project Developers"] name = "panic_unwind" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Implementation of Rust panics via stack unwinding" edition = "2018" [lib] diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 7f8f9c991fe..8cda601edd1 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -401,9 +401,10 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.52.0")] +// FIXME(#82080) The deprecation here is only theoretical, and does not actually produce a warning. +#[rustc_deprecated(reason = "moved to `std::ops::Bound`", since = "1.26.0")] #[doc(hidden)] -pub type Bound<T> = crate::ops::Bound<T>; +pub use crate::ops::Bound; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::collections::{binary_heap, btree_map, btree_set}; diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index ce52ffc0241..14914287cb1 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -716,7 +716,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤"); @@ -725,7 +724,7 @@ impl OsStr { /// /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn make_ascii_lowercase(&mut self) { self.inner.make_ascii_lowercase() @@ -742,7 +741,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let mut s = OsString::from("Grüße, Jürgen ❤"); @@ -751,7 +749,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn make_ascii_uppercase(&mut self) { self.inner.make_ascii_uppercase() @@ -768,13 +766,12 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// let s = OsString::from("Grüße, Jürgen ❤"); /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) } @@ -790,13 +787,12 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// let s = OsString::from("Grüße, Jürgen ❤"); /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) } @@ -806,7 +802,6 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// let ascii = OsString::from("hello!\n"); @@ -815,7 +810,7 @@ impl OsStr { /// assert!(ascii.is_ascii()); /// assert!(!non_ascii.is_ascii()); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] #[inline] pub fn is_ascii(&self) -> bool { self.inner.is_ascii() @@ -829,14 +824,13 @@ impl OsStr { /// # Examples /// /// ``` - /// #![feature(osstring_ascii)] /// use std::ffi::OsString; /// /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS")); /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS")); /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS")); /// ``` - #[unstable(feature = "osstring_ascii", issue = "70516")] + #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool { self.inner.eq_ignore_ascii_case(&other.as_ref().inner) } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 383eaf2e3a2..e64cbc18bf7 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1031,8 +1031,8 @@ mod mod_keyword {} /// }; /// ``` /// -/// For more information on the `move` keyword, see the [closure]'s section -/// of the Rust book or the [threads] section +/// For more information on the `move` keyword, see the [closures][closure] section +/// of the Rust book or the [threads] section. /// /// [closure]: ../book/ch13-01-closures.html /// [threads]: ../book/ch16-01-threads.html#using-move-closures-with-threads diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 1e79a5c3f9b..9b359392cf0 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -70,8 +70,6 @@ cfg_if::cfg_if! { #[allow(missing_docs)] pub mod unix_ext {} } else { - // On other platforms like Windows document the bare bones of unix - use crate::os::linux as platform; #[path = "unix/ext/mod.rs"] pub mod unix_ext; } diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs index ba75b9bac80..21bdfe29578 100644 --- a/library/std/src/sys/unix/ext/fs.rs +++ b/library/std/src/sys/unix/ext/fs.rs @@ -2,11 +2,11 @@ #![stable(feature = "rust1", since = "1.0.0")] +use super::platform::fs::MetadataExt as _; use crate::fs::{self, OpenOptions, Permissions}; use crate::io; use crate::path::Path; use crate::sys; -use crate::sys::platform::fs::MetadataExt as UnixMetadataExt; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; // Used for `File::read` on intra-doc links #[allow(unused_imports)] diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs index f4354688098..e5048f7e545 100644 --- a/library/std/src/sys/unix/ext/mod.rs +++ b/library/std/src/sys/unix/ext/mod.rs @@ -29,6 +29,42 @@ #![doc(cfg(unix))] #![allow(missing_docs)] +cfg_if::cfg_if! { + if #[cfg(doc)] { + // Use linux as the default platform when documenting on other platforms like Windows + use crate::os::linux as platform; + } else { + #[cfg(target_os = "android")] + use crate::os::android as platform; + #[cfg(target_os = "dragonfly")] + use crate::os::dragonfly as platform; + #[cfg(target_os = "emscripten")] + use crate::os::emscripten as platform; + #[cfg(target_os = "freebsd")] + use crate::os::freebsd as platform; + #[cfg(target_os = "fuchsia")] + use crate::os::fuchsia as platform; + #[cfg(target_os = "haiku")] + use crate::os::haiku as platform; + #[cfg(target_os = "illumos")] + use crate::os::illumos as platform; + #[cfg(target_os = "ios")] + use crate::os::ios as platform; + #[cfg(any(target_os = "linux", target_os = "l4re"))] + use crate::os::linux as platform; + #[cfg(target_os = "macos")] + use crate::os::macos as platform; + #[cfg(target_os = "netbsd")] + use crate::os::netbsd as platform; + #[cfg(target_os = "openbsd")] + use crate::os::openbsd as platform; + #[cfg(target_os = "redox")] + use crate::os::redox as platform; + #[cfg(target_os = "solaris")] + use crate::os::solaris as platform; + } +} + pub mod ffi; pub mod fs; pub mod io; diff --git a/library/std/src/sys/unix/ext/raw.rs b/library/std/src/sys/unix/ext/raw.rs index 3199a0bff0b..c292955cb4e 100644 --- a/library/std/src/sys/unix/ext/raw.rs +++ b/library/std/src/sys/unix/ext/raw.rs @@ -24,10 +24,10 @@ pub type pid_t = i32; #[doc(inline)] #[stable(feature = "pthread_t", since = "1.8.0")] -pub use crate::sys::platform::raw::pthread_t; +pub use super::platform::raw::pthread_t; #[doc(inline)] #[stable(feature = "raw_ext", since = "1.1.0")] -pub use crate::sys::platform::raw::{blkcnt_t, time_t}; +pub use super::platform::raw::{blkcnt_t, time_t}; #[doc(inline)] #[stable(feature = "raw_ext", since = "1.1.0")] -pub use crate::sys::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; +pub use super::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index f8a5ee89969..44328ffc22e 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -2,38 +2,6 @@ use crate::io::ErrorKind; -#[cfg(any(doc, target_os = "linux"))] -pub use crate::os::linux as platform; - -#[cfg(all(not(doc), target_os = "android"))] -pub use crate::os::android as platform; -#[cfg(all(not(doc), target_os = "dragonfly"))] -pub use crate::os::dragonfly as platform; -#[cfg(all(not(doc), target_os = "emscripten"))] -pub use crate::os::emscripten as platform; -#[cfg(all(not(doc), target_os = "freebsd"))] -pub use crate::os::freebsd as platform; -#[cfg(all(not(doc), target_os = "fuchsia"))] -pub use crate::os::fuchsia as platform; -#[cfg(all(not(doc), target_os = "haiku"))] -pub use crate::os::haiku as platform; -#[cfg(all(not(doc), target_os = "illumos"))] -pub use crate::os::illumos as platform; -#[cfg(all(not(doc), target_os = "ios"))] -pub use crate::os::ios as platform; -#[cfg(all(not(doc), target_os = "l4re"))] -pub use crate::os::linux as platform; -#[cfg(all(not(doc), target_os = "macos"))] -pub use crate::os::macos as platform; -#[cfg(all(not(doc), target_os = "netbsd"))] -pub use crate::os::netbsd as platform; -#[cfg(all(not(doc), target_os = "openbsd"))] -pub use crate::os::openbsd as platform; -#[cfg(all(not(doc), target_os = "redox"))] -pub use crate::os::redox as platform; -#[cfg(all(not(doc), target_os = "solaris"))] -pub use crate::os::solaris as platform; - pub use self::rand::hashmap_random_keys; pub use libc::strlen; diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 4f7a304a59f..69128591e06 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -2,6 +2,8 @@ authors = ["The Rust Project Developers"] name = "unwind" version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" edition = "2018" include = [ '/libunwind/*', diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 3e7d1d54f12..075756b73ba 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -463,6 +463,8 @@ class RustBuild(object): "--", "{}/src/llvm-project".format(top_level), "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level), + # the LLVM shared object file is named `LLVM-12-rust-{version}-nightly` + "{}/src/version".format(top_level) ]).decode(sys.getdefaultencoding()).strip() llvm_assertions = self.get_toml('assertions', 'llvm') == 'true' llvm_root = self.llvm_root() diff --git a/src/doc/reference b/src/doc/reference -Subproject e32a2f928f8b78d534bca2b9e7736413314dc55 +Subproject d10a0af8dca25d9d548ca6a369fd66ad06acb3c diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 8b5f5b66c45..6f283d501a4 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -296,7 +296,7 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { - ty::ConstKind::Unevaluated(def, _, promoted) => { + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { let mut s = if let Some(def) = def.as_local() { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did); print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id)) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bea0e75832c..60106f3b7ae 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -105,6 +105,10 @@ impl Buffer { crate fn is_for_html(&self) -> bool { self.for_html } + + crate fn reserve(&mut self, additional: usize) { + self.buffer.reserve(additional) + } } /// Wrapper struct for properly emitting a function or method declaration. diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 66c47f14655..128eac8cb0a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1009,18 +1009,25 @@ fn render_assoc_item( href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; - let mut header_len = format!( - "{}{}{}{}{}{:#}fn {}{:#}", - meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()), - header.constness.print_with_space(), - header.asyncness.print_with_space(), - header.unsafety.print_with_space(), - print_default_space(meth.is_default()), - print_abi_with_space(header.abi), - name, - g.print(cx.cache()) - ) - .len(); + let tcx = cx.tcx(); + let vis = meth.visibility.print_with_space(tcx, meth.def_id, cx.cache()).to_string(); + let constness = header.constness.print_with_space(); + let asyncness = header.asyncness.print_with_space(); + let unsafety = header.unsafety.print_with_space(); + let defaultness = print_default_space(meth.is_default()); + let abi = print_abi_with_space(header.abi).to_string(); + // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`. + let generics_len = format!("{:#}", g.print(cx.cache())).len(); + let mut header_len = "fn ".len() + + vis.len() + + constness.len() + + asyncness.len() + + unsafety.len() + + defaultness.len() + + abi.len() + + name.as_str().len() + + generics_len; + let (indent, end_newline) = if parent == ItemType::Trait { header_len += 4; (4, false) @@ -1028,17 +1035,18 @@ fn render_assoc_item( (0, true) }; render_attributes(w, meth, false); + w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len()); write!( w, "{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\ {generics}{decl}{spotlight}{where_clause}", if parent == ItemType::Trait { " " } else { "" }, - meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()), - header.constness.print_with_space(), - header.asyncness.print_with_space(), - header.unsafety.print_with_space(), - print_default_space(meth.is_default()), - print_abi_with_space(header.abi), + vis, + constness, + asyncness, + unsafety, + defaultness, + abi, href = href, name = name, generics = g.print(cx.cache()), diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index e7b522093c7..f1ecaaa619c 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,3 +1,4 @@ +// ignore-tidy-filelength // Local js definitions: /* global addClass, getSettingValue, hasClass */ /* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */ @@ -374,28 +375,35 @@ function defocusSearchBar() { } } - function getHelpElement() { - buildHelperPopup(); + function getHelpElement(build) { + if (build !== false) { + buildHelperPopup(); + } return document.getElementById("help"); } function displayHelp(display, ev, help) { - help = help ? help : getHelpElement(); if (display === true) { + help = help ? help : getHelpElement(true); if (hasClass(help, "hidden")) { ev.preventDefault(); removeClass(help, "hidden"); addClass(document.body, "blur"); } - } else if (hasClass(help, "hidden") === false) { - ev.preventDefault(); - addClass(help, "hidden"); - removeClass(document.body, "blur"); + } else { + // No need to build the help popup if we want to hide it in case it hasn't been + // built yet... + help = help ? help : getHelpElement(false); + if (help && hasClass(help, "hidden") === false) { + ev.preventDefault(); + addClass(help, "hidden"); + removeClass(document.body, "blur"); + } } } function handleEscape(ev) { - var help = getHelpElement(); + var help = getHelpElement(false); var search = getSearchElement(); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); @@ -558,6 +566,7 @@ function defocusSearchBar() { }()); document.addEventListener("click", function(ev) { + var helpElem = getHelpElement(false); if (hasClass(ev.target, "help-button")) { displayHelp(true, ev); } else if (hasClass(ev.target, "collapse-toggle")) { @@ -566,11 +575,10 @@ function defocusSearchBar() { collapseDocs(ev.target.parentNode, "toggle"); } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { handleSourceHighlight(ev); - } else if (hasClass(getHelpElement(), "hidden") === false) { - var help = getHelpElement(); - var is_inside_help_popup = ev.target !== help && help.contains(ev.target); + } else if (helpElem && hasClass(helpElem, "hidden") === false) { + var is_inside_help_popup = ev.target !== helpElem && helpElem.contains(ev.target); if (is_inside_help_popup === false) { - addClass(help, "hidden"); + addClass(helpElem, "hidden"); removeClass(document.body, "blur"); } } else { diff --git a/src/llvm-project b/src/llvm-project -Subproject 62a1ddde22c267249eda72184520a21ad2052f0 +Subproject c3a26cbf6e73f2c5f8d03cee1f151d90a266ef3 diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index a1da4faf5d8..0c34bf1b914 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes // ignore-tidy-linelength // min-system-llvm-version: 12.0 @@ -43,13 +43,13 @@ pub fn named_borrow<'r>(_: &'r i32) { pub fn unsafe_borrow(_: &UnsafeInner) { } -// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %_1) +// CHECK: @mutable_unsafe_borrow(i16* noalias align 2 dereferenceable(2) %_1) // ... unless this is a mutable borrow, those never alias #[no_mangle] pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { } -// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %_1) +// CHECK: @mutable_borrow(i32* noalias align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_borrow(_: &mut i32) { @@ -94,7 +94,7 @@ pub fn helper(_: usize) { pub fn slice(_: &[u8]) { } -// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %_1.0, [[USIZE]] %_1.1) +// CHECK: @mutable_slice([0 x i8]* noalias nonnull align 1 %_1.0, [[USIZE]] %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_slice(_: &mut [u8]) { diff --git a/src/test/codegen/noalias-unpin.rs b/src/test/codegen/noalias-unpin.rs new file mode 100644 index 00000000000..8ca9b98eee2 --- /dev/null +++ b/src/test/codegen/noalias-unpin.rs @@ -0,0 +1,15 @@ +// compile-flags: -O -Z mutable-noalias=yes + +#![crate_type = "lib"] + +pub struct SelfRef { + self_ref: *mut SelfRef, + _pin: std::marker::PhantomPinned +} + +// CHECK-LABEL: @test_self_ref( +// CHECK-NOT: noalias +#[no_mangle] +pub unsafe fn test_self_ref(s: &mut SelfRef) { + (*s.self_ref).self_ref = std::ptr::null_mut(); +} diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index c31e8457dcd..6ab28e87cb6 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -1,5 +1,5 @@ // ignore-tidy-linelength -// compile-flags: -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs new file mode 100644 index 00000000000..72ed7492be9 --- /dev/null +++ b/src/test/codegen/vec-in-place.rs @@ -0,0 +1,14 @@ +// ignore-debug: the debug assertions get in the way +// compile-flags: -O +// min-llvm-version: 11.0 +#![crate_type = "lib"] + +// Ensure that trivial casts of vec elements are O(1) + +// CHECK-LABEL: @vec_iterator_cast +#[no_mangle] +pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> { + // CHECK-NOT: loop + // CHECK-NOT: call + vec.into_iter().map(|e| e as usize).collect() +} diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 5ba76c4f0bd..4e990dd6b70 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -22,7 +22,7 @@ - // + ty: &i32 - // + val: Value(Scalar(alloc0)) + // + ty: &[&i32; 1] -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, [], Some(promoted[0])) ++ // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } @@ -30,7 +30,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, [], Some(promoted[0])) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35 diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 1565cc7d5e7..0a9a3f3c2c5 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -24,7 +24,7 @@ - // + ty: *const i32 - // + val: Value(Scalar(alloc2)) + // + ty: &[&i32; 1] -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, [], Some(promoted[0])) ++ // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) } @@ -32,7 +32,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, [], Some(promoted[0])) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 8c10b3518d8..baa8988f152 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -28,10 +28,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // ty::Const // + ty: &[i32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 8c10b3518d8..baa8988f152 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -28,10 +28,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // ty::Const // + ty: &[i32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index 60346458646..8ba11df7e0e 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -19,10 +19,10 @@ _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, [], None) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, [], None) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 _1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39 StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39 diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 4fd1b8b2276..56683d7ef03 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -14,10 +14,10 @@ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/ref_deref.rs:5:6: 5:10 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 + _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff index e7ebfee7f3e..e1c8085b31b 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff @@ -17,10 +17,10 @@ + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 + // ty::Const + // + ty: &i32 -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) ++ // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) + // mir::Constant + // + span: $DIR/ref_deref.rs:5:6: 5:10 -+ // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) } ++ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 - StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 812c7c97718..cce4831b6fe 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -14,10 +14,10 @@ _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 // ty::Const // + ty: &(i32, i32) - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/ref_deref_project.rs:5:6: 5:17 - // + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff index 588c291bcc3..93ba9de8202 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff @@ -17,10 +17,10 @@ + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 + // ty::Const + // + ty: &(i32, i32) -+ // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) ++ // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) + // mir::Constant + // + span: $DIR/ref_deref_project.rs:5:6: 5:17 -+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) } ++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 - StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 240cc8e2311..20f93f874c5 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -21,10 +21,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 // ty::Const // + ty: &[u32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 240cc8e2311..20f93f874c5 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -21,10 +21,10 @@ _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 // ty::Const // + ty: &[u32; 3] - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/early_otherwise_branch.rs b/src/test/mir-opt/early_otherwise_branch.rs index 548213ab83c..b2caf7d7b8f 100644 --- a/src/test/mir-opt/early_otherwise_branch.rs +++ b/src/test/mir-opt/early_otherwise_branch.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z mir-opt-level=4 +// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts // EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff fn opt1(x: Option<u32>, y: Option<u32>) -> u32 { match (x, y) { diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs index aa304f747f7..8527c01d756 100644 --- a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs +++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z mir-opt-level=4 +// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts // EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 { diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index b9fe84fcd04..0b5dc2b20fc 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -35,10 +35,10 @@ fn bar() -> bool { _10 = const bar::promoted[1]; // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[1])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) // mir::Constant // + span: $DIR/inline-retag.rs:12:7: 12:9 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[1])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) } Retag(_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 _4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 Retag(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 @@ -49,10 +49,10 @@ fn bar() -> bool { _9 = const bar::promoted[0]; // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/inline-retag.rs:12:11: 12:14 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } Retag(_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 _7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 Retag(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index f6e6614bb6e..1ba56016776 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -63,10 +63,10 @@ _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index f6e6614bb6e..1ba56016776 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -63,10 +63,10 @@ _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index bd24522271b..5ae26b73a65 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -84,10 +84,10 @@ _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index bd24522271b..5ae26b73a65 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -84,10 +84,10 @@ _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 7da2ff02006..83650d837b0 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -47,10 +47,10 @@ _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[2])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) // mir::Constant // + span: $DIR/lower_intrinsics.rs:70:42: 70:44 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[2])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) } _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 @@ -71,10 +71,10 @@ _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 // ty::Const // + ty: &() - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[1])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) // mir::Constant // + span: $DIR/lower_intrinsics.rs:71:42: 71:45 - // + literal: Const { ty: &(), val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[1])) } + // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) } _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 @@ -95,10 +95,10 @@ _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 // ty::Const // + ty: &E - // + val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/lower_intrinsics.rs:72:42: 72:47 - // + literal: Const { ty: &E, val: Unevaluated(WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, [T], Some(promoted[0])) } + // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) } _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir index 2332e5beafe..242138754c5 100644 --- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir +++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir @@ -54,10 +54,10 @@ fn full_tested_match() -> () { _11 = const full_tested_match::promoted[0]; // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 // ty::Const // + ty: &std::option::Option<i32> - // + val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/match_false_edges.rs:16:14: 16:15 - // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 _4 = &shallow _2; // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 StorageLive(_7); // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27 diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 8c7d79262b2..d25f98db9f6 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -149,10 +149,10 @@ fn main() -> () { _27 = const main::promoted[0]; // scope 7 at $DIR/retag.rs:47:21: 47:23 // ty::Const // + ty: &i32 - // + val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, [], Some(promoted[0])) + // + val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) // mir::Constant // + span: $DIR/retag.rs:47:21: 47:23 - // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } Retag(_27); // scope 7 at $DIR/retag.rs:47:21: 47:23 _23 = &(*_27); // scope 7 at $DIR/retag.rs:47:21: 47:23 Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr index b1b61f0211a..78b85dfde33 100644 --- a/src/test/ui/asm/inline-syntax.arm.stderr +++ b/src/test/ui/asm/inline-syntax.arm.stderr @@ -1,11 +1,11 @@ error: att syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:22:15 + --> $DIR/inline-syntax.rs:23:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: att syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:25:15 + --> $DIR/inline-syntax.rs:26:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs index 9e9c7badfca..9048282456e 100644 --- a/src/test/ui/asm/inline-syntax.rs +++ b/src/test/ui/asm/inline-syntax.rs @@ -1,3 +1,4 @@ +// needs-llvm-components: arm // revisions: x86_64 arm //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu //[arm] compile-flags: --target armv7-unknown-linux-gnueabihf diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr index c54c2742a57..826657c98e1 100644 --- a/src/test/ui/asm/inline-syntax.x86_64.stderr +++ b/src/test/ui/asm/inline-syntax.x86_64.stderr @@ -1,17 +1,17 @@ error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:18:15 + --> $DIR/inline-syntax.rs:19:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:20:15 + --> $DIR/inline-syntax.rs:21:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:22:15 + --> $DIR/inline-syntax.rs:23:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | asm!("", "nop", options(att_syntax)); | -- ^^^^^^^^^^^^^^^^^^^^^ error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:25:15 + --> $DIR/inline-syntax.rs:26:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,13 +33,13 @@ LL | asm!("", "nop", options(att_syntax)); | -- ^^^^^^^^^^^^^^^^^^^^^ error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:28:15 + --> $DIR/inline-syntax.rs:29:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:33:14 + --> $DIR/inline-syntax.rs:34:14 | LL | .intel_syntax noprefix | ______________^ diff --git a/src/test/ui/issues/issue-23208.rs b/src/test/ui/associated-types/issue-23208.rs index fd4ffe5d6e1..fd4ffe5d6e1 100644 --- a/src/test/ui/issues/issue-23208.rs +++ b/src/test/ui/associated-types/issue-23208.rs diff --git a/src/test/ui/issues/issue-31597.rs b/src/test/ui/associated-types/issue-31597.rs index 2872be6d6c8..2872be6d6c8 100644 --- a/src/test/ui/issues/issue-31597.rs +++ b/src/test/ui/associated-types/issue-31597.rs diff --git a/src/test/ui/shadow.rs b/src/test/ui/binding/shadow.rs index 2495c8f47e7..2495c8f47e7 100644 --- a/src/test/ui/shadow.rs +++ b/src/test/ui/binding/shadow.rs diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr index 1beb5315d10..84b2665d5bf 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr @@ -3,48 +3,52 @@ error: unconstrained generic constant | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10 | LL | [u8; std::mem::size_of::<T>() - 1]: Sized, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27 | LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10 | LL | [u8; std::mem::size_of::<T>() - 1]: Sized, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: unconstrained generic constant --> $DIR/cross_crate_predicate.rs:7:13 | LL | let _ = const_evaluatable_lib::test1::<T>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound using this expression: `where [u8; std::mem::size_of::<T>() - 1]: Sized` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | + ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27 | LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------------------- required by this bound in `test1` + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr index 8cdc9b57750..7c11a47b2f0 100644 --- a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr +++ b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | [0; size_of::<Foo<T>>()] | ^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; size_of::<Foo<T>>()]: Sized` - --> $DIR/different-fn.rs:10:9 - | -LL | [0; size_of::<Foo<T>>()] - | ^^^^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:` error: aborting due to previous error diff --git a/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs b/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 00000000000..92a410afcb1 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(const_generics)] +#![feature(const_evaluatable_checked)] +#![allow(incomplete_features)] + +// This test is a repro for #82279. It checks that we don't error +// when calling is_const_evaluatable on `std::mem::size_of::<T>()` +// when looking for candidates that may prove `T: Foo` in `foo` + +trait Foo {} + +#[allow(dead_code)] +fn foo<T: Foo>() {} + +impl<T> Foo for T where [(); std::mem::size_of::<T>()]: {} + +fn main() {} diff --git a/src/test/ui/const-generics/type_mismatch.rs b/src/test/ui/const-generics/type_mismatch.rs new file mode 100644 index 00000000000..4a7534e3713 --- /dev/null +++ b/src/test/ui/const-generics/type_mismatch.rs @@ -0,0 +1,9 @@ +fn foo<const N: usize>() -> [u8; N] { + bar::<N>() //~ ERROR mismatched types +} + +fn bar<const N: u8>() -> [u8; N] {} +//~^ ERROR mismatched types +//~| ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/const-generics/type_mismatch.stderr b/src/test/ui/const-generics/type_mismatch.stderr new file mode 100644 index 00000000000..f5053e4c8c8 --- /dev/null +++ b/src/test/ui/const-generics/type_mismatch.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::<N>() + | ^ expected `u8`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:31 + | +LL | fn bar<const N: u8>() -> [u8; N] {} + | ^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:26 + | +LL | fn bar<const N: u8>() -> [u8; N] {} + | --- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/type_not_in_scope.rs b/src/test/ui/const-generics/type_not_in_scope.rs new file mode 100644 index 00000000000..5933701808b --- /dev/null +++ b/src/test/ui/const-generics/type_not_in_scope.rs @@ -0,0 +1,11 @@ +impl X { + //~^ ERROR cannot find type + fn getn<const N: usize>() -> [u8; N] { + getn::<N>() + } +} +fn getn<const N: cfg_attr>() -> [u8; N] {} +//~^ ERROR expected type, found built-in attribute `cfg_attr` +//~| ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/const-generics/type_not_in_scope.stderr b/src/test/ui/const-generics/type_not_in_scope.stderr new file mode 100644 index 00000000000..16796acb3d2 --- /dev/null +++ b/src/test/ui/const-generics/type_not_in_scope.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `X` in this scope + --> $DIR/type_not_in_scope.rs:1:6 + | +LL | impl X { + | ^ not found in this scope + +error[E0573]: expected type, found built-in attribute `cfg_attr` + --> $DIR/type_not_in_scope.rs:7:18 + | +LL | fn getn<const N: cfg_attr>() -> [u8; N] {} + | ^^^^^^^^ not a type + +error[E0308]: mismatched types + --> $DIR/type_not_in_scope.rs:7:33 + | +LL | fn getn<const N: cfg_attr>() -> [u8; N] {} + | ---- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0412, E0573. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/const_evaluatable/needs_where_clause.stderr b/src/test/ui/const_evaluatable/needs_where_clause.stderr index 945105d1a2d..7b41e39b7d7 100644 --- a/src/test/ui/const_evaluatable/needs_where_clause.stderr +++ b/src/test/ui/const_evaluatable/needs_where_clause.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | b: [f32; complex_maths::<T>(N)], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; complex_maths::<T>(N)]: Sized` - --> $DIR/needs_where_clause.rs:11:12 - | -LL | b: [f32; complex_maths::<T>(N)], - | ^^^^^^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:` error: aborting due to previous error diff --git a/src/test/ui/const_evaluatable/no_where_clause.stderr b/src/test/ui/const_evaluatable/no_where_clause.stderr index 84a65f0d1d2..3e5c2f5cad1 100644 --- a/src/test/ui/const_evaluatable/no_where_clause.stderr +++ b/src/test/ui/const_evaluatable/no_where_clause.stderr @@ -4,11 +4,7 @@ error: unconstrained generic constant LL | b: [f32; complex_maths(N)], | ^^^^^^^^^^^^^^^^^^^^^^^ | -help: try adding a `where` bound using this expression: `where [u8; complex_maths(N)]: Sized` - --> $DIR/no_where_clause.rs:10:12 - | -LL | b: [f32; complex_maths(N)], - | ^^^^^^^^^^^^^^^^ + = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/consts/issue-52060.rs index 13b914c0331..13b914c0331 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/consts/issue-52060.rs diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/consts/issue-52060.stderr index 95e5f2a8282..95e5f2a8282 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/consts/issue-52060.stderr diff --git a/src/test/ui/mir_check_nonconst.rs b/src/test/ui/consts/mir_check_nonconst.rs index b8ec0c3c449..b8ec0c3c449 100644 --- a/src/test/ui/mir_check_nonconst.rs +++ b/src/test/ui/consts/mir_check_nonconst.rs diff --git a/src/test/ui/mir_check_nonconst.stderr b/src/test/ui/consts/mir_check_nonconst.stderr index 30f68ba4372..30f68ba4372 100644 --- a/src/test/ui/mir_check_nonconst.stderr +++ b/src/test/ui/consts/mir_check_nonconst.stderr diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.rs b/src/test/ui/generator/issue-45729-unsafe-in-generator.rs index 638a1994bb5..638a1994bb5 100644 --- a/src/test/ui/issues/issue-45729-unsafe-in-generator.rs +++ b/src/test/ui/generator/issue-45729-unsafe-in-generator.rs diff --git a/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr b/src/test/ui/generator/issue-45729-unsafe-in-generator.stderr index 2aab6807aaa..2aab6807aaa 100644 --- a/src/test/ui/issues/issue-45729-unsafe-in-generator.stderr +++ b/src/test/ui/generator/issue-45729-unsafe-in-generator.stderr diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.rs b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs index fd8fe5f48df..fd8fe5f48df 100644 --- a/src/test/ui/impl-trait-in-bindings-issue-73003.rs +++ b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.rs diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr index 715671c8add..715671c8add 100644 --- a/src/test/ui/impl-trait-in-bindings-issue-73003.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-bindings-issue-73003.stderr diff --git a/src/test/ui/impl-trait-in-bindings.rs b/src/test/ui/impl-trait/impl-trait-in-bindings.rs index c7fae45d5ca..c7fae45d5ca 100644 --- a/src/test/ui/impl-trait-in-bindings.rs +++ b/src/test/ui/impl-trait/impl-trait-in-bindings.rs diff --git a/src/test/ui/impl-trait-in-bindings.stderr b/src/test/ui/impl-trait/impl-trait-in-bindings.stderr index bf739d4722f..bf739d4722f 100644 --- a/src/test/ui/impl-trait-in-bindings.stderr +++ b/src/test/ui/impl-trait/impl-trait-in-bindings.stderr diff --git a/src/test/ui/imports/tool-mod-child.rs b/src/test/ui/imports/tool-mod-child.rs new file mode 100644 index 00000000000..4581dc2e2ad --- /dev/null +++ b/src/test/ui/imports/tool-mod-child.rs @@ -0,0 +1,7 @@ +use clippy::a; //~ ERROR unresolved import `clippy` +use clippy::a::b; //~ ERROR failed to resolve: maybe a missing crate `clippy`? + +use rustdoc::a; //~ ERROR unresolved import `rustdoc` +use rustdoc::a::b; //~ ERROR failed to resolve: maybe a missing crate `rustdoc`? + +fn main() {} diff --git a/src/test/ui/imports/tool-mod-child.stderr b/src/test/ui/imports/tool-mod-child.stderr new file mode 100644 index 00000000000..efab4f6a74f --- /dev/null +++ b/src/test/ui/imports/tool-mod-child.stderr @@ -0,0 +1,28 @@ +error[E0433]: failed to resolve: maybe a missing crate `clippy`? + --> $DIR/tool-mod-child.rs:2:5 + | +LL | use clippy::a::b; + | ^^^^^^ maybe a missing crate `clippy`? + +error[E0432]: unresolved import `clippy` + --> $DIR/tool-mod-child.rs:1:5 + | +LL | use clippy::a; + | ^^^^^^ maybe a missing crate `clippy`? + +error[E0433]: failed to resolve: maybe a missing crate `rustdoc`? + --> $DIR/tool-mod-child.rs:5:5 + | +LL | use rustdoc::a::b; + | ^^^^^^^ maybe a missing crate `rustdoc`? + +error[E0432]: unresolved import `rustdoc` + --> $DIR/tool-mod-child.rs:4:5 + | +LL | use rustdoc::a; + | ^^^^^^^ maybe a missing crate `rustdoc`? + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs index b4e9da0fc84..b4e9da0fc84 100644 --- a/src/test/ui/fn_must_use.rs +++ b/src/test/ui/lint/fn_must_use.rs diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr index d6b1cf3ae1f..d6b1cf3ae1f 100644 --- a/src/test/ui/fn_must_use.stderr +++ b/src/test/ui/lint/fn_must_use.stderr diff --git a/src/test/ui/concat-rpass.rs b/src/test/ui/macros/concat-rpass.rs index 0c30a39d6a2..0c30a39d6a2 100644 --- a/src/test/ui/concat-rpass.rs +++ b/src/test/ui/macros/concat-rpass.rs diff --git a/src/test/ui/issues/issue-48508-aux.rs b/src/test/ui/parser/issue-48508-aux.rs index ebdc70a04df..ebdc70a04df 100644 --- a/src/test/ui/issues/issue-48508-aux.rs +++ b/src/test/ui/parser/issue-48508-aux.rs diff --git a/src/test/ui/issues/issue-48508.rs b/src/test/ui/parser/issue-48508.rs index 8dc9351260e..8dc9351260e 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/parser/issue-48508.rs diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs index 3c49a5a9752..3c49a5a9752 100644 --- a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs +++ b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.rs diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr index ef365a61643..ef365a61643 100644 --- a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr +++ b/src/test/ui/parser/issue-68000-unicode-ident-after-missing-comma.stderr diff --git a/src/test/ui/issues/issue-10392.rs b/src/test/ui/pattern/issue-10392.rs index 926fa94800e..926fa94800e 100644 --- a/src/test/ui/issues/issue-10392.rs +++ b/src/test/ui/pattern/issue-10392.rs diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs index 1a500361640..7a46aee462b 100644 --- a/src/test/ui/proc-macro/auxiliary/test-macros.rs +++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs @@ -83,21 +83,52 @@ fn print_helper(input: TokenStream, kind: &str) -> TokenStream { print_helper_ext(input, kind, true) } +fn deep_recollect(input: TokenStream) -> TokenStream { + input.into_iter().map(|tree| { + match tree { + TokenTree::Group(group) => { + let inner = deep_recollect(group.stream()); + let mut new_group = TokenTree::Group( + proc_macro::Group::new(group.delimiter(), inner) + ); + new_group.set_span(group.span()); + new_group + } + _ => tree, + } + }).collect() +} + fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream { let input_display = format!("{}", input); let input_debug = format!("{:#?}", input); - let recollected = input.into_iter().collect(); + let recollected = input.clone().into_iter().collect(); let recollected_display = format!("{}", recollected); let recollected_debug = format!("{:#?}", recollected); + + let deep_recollected = deep_recollect(input); + let deep_recollected_display = format!("{}", deep_recollected); + let deep_recollected_debug = format!("{:#?}", deep_recollected); + + + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); if recollected_display != input_display { println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); } + + if deep_recollected_display != recollected_display { + println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display); + } + if debug { println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); if recollected_debug != input_debug { println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); } + if deep_recollected_debug != recollected_debug { + println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug); + } } recollected } diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs index d9687490cad..2b742771d6f 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs @@ -43,7 +43,8 @@ mod with_version { struct Foo; impl_macros!(Foo); //~ WARN using an old version //~| WARN this was previously - arrays!(Foo); + arrays!(Foo); //~ WARN using an old version + //~| WARN this was previously other!(Foo); } @@ -77,5 +78,11 @@ mod actori_web_version_test { tuple_from_req!(Foo); } +mod with_good_js_sys_version { + include!("js-sys-0.3.40/src/lib.rs"); + struct Foo; + arrays!(Foo); +} + fn main() {} diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr index e2b680f8d27..effcd68cf96 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr @@ -31,13 +31,29 @@ LL | impl_macros!(Foo); = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +warning: using an old version of `js-sys` + --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 + | +LL | #[my_macro] struct Two($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:46:5 + | +LL | arrays!(Foo); + | ------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 | LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:54:5 + ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -53,7 +69,7 @@ warning: using an old version of `actix-web` LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:62:5 + ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -63,7 +79,7 @@ LL | tuple_from_req!(Foo); = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 4 warnings emitted +warning: 5 warnings emitted Future incompatibility report: Future breakage date: None, diagnostic: warning: using an old version of `time-macros-impl` @@ -101,13 +117,30 @@ LL | impl_macros!(Foo); = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage date: None, diagnostic: +warning: using an old version of `js-sys` + --> $DIR/js-sys-0.3.17/src/lib.rs:5:32 + | +LL | #[my_macro] struct Two($name); + | ^^^^^ + | + ::: $DIR/group-compat-hack.rs:46:5 + | +LL | arrays!(Foo); + | ------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125> + = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage date: None, diagnostic: warning: using an old version of `actix-web` --> $DIR/actix-web/src/extract.rs:5:34 | LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:54:5 + ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation @@ -124,7 +157,7 @@ warning: using an old version of `actix-web` LL | #[my_macro] struct Three($T); | ^^ | - ::: $DIR/group-compat-hack.rs:62:5 + ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); | --------------------- in this macro invocation diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout index 3fe744e12ff..82d6bc33bf9 100644 --- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout +++ b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout @@ -1,10 +1,11 @@ Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:27:18: 27:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:13: 29:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:32: 5:37 (#10) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:22:25: 22:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:22:32: 22:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:30:12: 30:15 (#0) }], span: $DIR/group-compat-hack.rs:22:38: 22:43 (#14) }], span: $DIR/group-compat-hack.rs:22:37: 22:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:22:44: 22:45 (#14) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:44:18: 44:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }] Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:46:13: 46:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:62:21: 62:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:70:21: 70:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] -Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:77:21: 77:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:39:25: 39:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:39:32: 39:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:48:12: 48:15 (#0) }], span: $DIR/group-compat-hack.rs:39:38: 39:43 (#28) }], span: $DIR/group-compat-hack.rs:39:37: 39:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:39:44: 39:45 (#28) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:55:21: 55:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:63:21: 63:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:71:21: 71:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:78:21: 78:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }] +Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.40/src/lib.rs:5:21: 5:27 (#53) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.40/src/lib.rs:5:28: 5:31 (#53) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:84:13: 84:16 (#0) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:32: 5:37 (#53) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:31: 5:38 (#53) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.40/src/lib.rs:5:38: 5:39 (#53) }] diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs new file mode 100644 index 00000000000..d1a66940ebf --- /dev/null +++ b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs @@ -0,0 +1,7 @@ +// ignore-test this is not a test + +macro_rules! arrays { + ($name:ident) => { + #[my_macro] struct Two($name); + } +} diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout index 40da5aa93bf..9b467a5970b 100644 --- a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout +++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout @@ -1,6 +1,7 @@ PRINT-BANG INPUT (DISPLAY): foo ! { #[fake_attr] mod bar { #![doc = r" Foo"] } } +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo ! { #[fake_attr] mod bar { # ! [doc = r" Foo"] } } PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "foo", diff --git a/src/test/ui/proc-macro/nodelim-groups.stdout b/src/test/ui/proc-macro/nodelim-groups.stdout index 6b410f0bfb7..4ffe3f35e8e 100644 --- a/src/test/ui/proc-macro/nodelim-groups.stdout +++ b/src/test/ui/proc-macro/nodelim-groups.stdout @@ -71,6 +71,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1) +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): "hi" "hello" . len() + "world" . len() (1 + 1) PRINT-BANG INPUT (DEBUG): TokenStream [ Literal { kind: Str, diff --git a/src/test/ui/no-implicit-prelude.rs b/src/test/ui/resolve/no-implicit-prelude.rs index 4b0ca4d524e..4b0ca4d524e 100644 --- a/src/test/ui/no-implicit-prelude.rs +++ b/src/test/ui/resolve/no-implicit-prelude.rs diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/resolve/no-implicit-prelude.stderr index 36a9b65b7d1..36a9b65b7d1 100644 --- a/src/test/ui/no-implicit-prelude.stderr +++ b/src/test/ui/resolve/no-implicit-prelude.stderr diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs index f95f548fee8..3576eed71ab 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs @@ -25,6 +25,8 @@ extern "platform-intrinsic" { fn simd_and<T>(x: T, y: T) -> T; fn simd_or<T>(x: T, y: T) -> T; fn simd_xor<T>(x: T, y: T) -> T; + + fn simd_neg<T>(x: T) -> T; } fn main() { @@ -60,6 +62,9 @@ fn main() { simd_xor(x, x); simd_xor(y, y); + simd_neg(x); + simd_neg(z); + simd_add(0, 0); //~^ ERROR expected SIMD input type, found non-SIMD `i32` @@ -80,6 +85,9 @@ fn main() { simd_xor(0, 0); //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_neg(0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_shl(z, z); //~^ ERROR unsupported operation on `f32x4` with element `f32` diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr index 70cdc34684d..99c51963343 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr @@ -1,87 +1,93 @@ error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:64:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:69:9 | LL | simd_add(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:66:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:71:9 | LL | simd_sub(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:68:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:73:9 | LL | simd_mul(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:70:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:75:9 | LL | simd_div(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:72:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:77:9 | LL | simd_shl(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:74:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:79:9 | LL | simd_shr(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:76:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:81:9 | LL | simd_and(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:78:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:83:9 | LL | simd_or(0, 0); | ^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:80:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:85:9 | LL | simd_xor(0, 0); | ^^^^^^^^^^^^^^ +error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9 + | +LL | simd_neg(0); + | ^^^^^^^^^^^ + error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:84:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:92:9 | LL | simd_shl(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:86:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:94:9 | LL | simd_shr(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:96:9 | LL | simd_and(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:90:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:98:9 | LL | simd_or(z, z); | ^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:92:9 + --> $DIR/simd-intrinsic-generic-arithmetic.rs:100:9 | LL | simd_xor(z, z); | ^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs index 96c2c6c5399..c507b8d31ec 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs @@ -45,6 +45,8 @@ extern "platform-intrinsic" { fn simd_and<T>(x: T, y: T) -> T; fn simd_or<T>(x: T, y: T) -> T; fn simd_xor<T>(x: T, y: T) -> T; + + fn simd_neg<T>(x: T) -> T; } fn main() { @@ -125,5 +127,10 @@ fn main() { all_eq_!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); all_eq_!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_neg(x1), i32x4(-1, -2, -3, -4)); + all_eq!(simd_neg(x2), i32x4(-2, -3, -4, -5)); + all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0)); + all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0)); + } } diff --git a/src/test/ui/issues/issue-1701.rs b/src/test/ui/structs-enums/issue-1701.rs index bae32a77765..bae32a77765 100644 --- a/src/test/ui/issues/issue-1701.rs +++ b/src/test/ui/structs-enums/issue-1701.rs diff --git a/src/test/ui/issues/issue-78372.rs b/src/test/ui/traits/issue-78372.rs index 77a8c92c81c..77a8c92c81c 100644 --- a/src/test/ui/issues/issue-78372.rs +++ b/src/test/ui/traits/issue-78372.rs diff --git a/src/test/ui/issues/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr index 9267e838cea..9267e838cea 100644 --- a/src/test/ui/issues/issue-78372.stderr +++ b/src/test/ui/traits/issue-78372.stderr diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/typeck/issue-65611.rs index b74ee1b0c6e..b74ee1b0c6e 100644 --- a/src/test/ui/issues/issue-65611.rs +++ b/src/test/ui/typeck/issue-65611.rs diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/typeck/issue-65611.stderr index e3c005a0593..e3c005a0593 100644 --- a/src/test/ui/issues/issue-65611.stderr +++ b/src/test/ui/typeck/issue-65611.stderr diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 8aebce67917..3e1db233696 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -181,7 +181,15 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D let result = cx .tcx - .const_eval_resolve(cx.param_env, ty::WithOptConstParam::unknown(def_id), substs, None, None); + .const_eval_resolve( + cx.param_env, + ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), + substs, + promoted: None + }, + None + ); is_value_unfrozen_raw(cx, result, ty) } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 802c01055a6..ebe896b7ae8 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -341,9 +341,11 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { .tcx .const_eval_resolve( self.param_env, - ty::WithOptConstParam::unknown(def_id), - substs, - None, + ty::Unevaluated { + def: ty::WithOptConstParam::unknown(def_id), + substs, + promoted: None, + }, None, ) .ok() diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3374a8c9b73..7cc660454b4 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,8 +7,8 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 1408; -const ISSUES_ENTRY_LIMIT: usize = 2565; +const ROOT_ENTRY_LIMIT: usize = 1390; +const ISSUES_ENTRY_LIMIT: usize = 2551; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui")) diff --git a/src/version b/src/version index a63cb35e6f0..3f4830156cb 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.52.0 +1.53.0 |
