<ins> // run-pass #![feature(adt_const_params, generic_const_exprs)] #![allow(incomplete_features, unused_variables)] struct F<const S: &'static str>; impl<const S: &'static str> X for F<{ S }> { const W: usize = 3; fn d(r: &[u8; Self::W]) -> F<{ S }> { let x: [u8; Self::W] = [0; Self::W]; F } } pub trait X { const W: usize; fn d(r: &[u8; Self::W]) -> Self; } fn main() {} </ins>


<ins> trait Trait<const N: usize> { const Assoc: usize; } impl<const N: usize> Trait<N> for () { const Assoc: usize = 1; } pub const fn foo<const N: usize>() where (): Trait<N> { let bar = [(); <()>::Assoc]; //~^ error: constant expression depends on a generic parameter } trait Trait2<const N: usize> { const Assoc2: usize; } impl<const N: usize> Trait2<N> for () { const Assoc2: usize = N - 1; } pub const fn foo2<const N: usize>() where (): Trait2<N> { let bar2 = [(); <()>::Assoc2]; //~^ error: constant expression depends on a generic parameter } fn main() { foo::<0>(); foo2::<0>(); } </ins>


<ins> error: constant expression depends on a generic parameter --> $DIR/sneaky-array-repeat-expr.rs:11:20 | LL |     let bar = [(); <()>::Assoc]; |                    ^^^^^^^^^^^ | = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter --> $DIR/sneaky-array-repeat-expr.rs:25:21 | LL |     let bar2 = [(); <()>::Assoc2]; |                     ^^^^^^^^^^^^ | = note: this may fail depending on what value the parameter takes error: aborting due to 2 previous errors </ins>


} macro_rules! tool_doc { <del> ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(, binary=$bin:expr)?) => { </del> <ins> ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], binary=$bin:expr) => { </ins> #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $tool { stage: u32,


cargo.arg("-p").arg($krate); )+ <del> $(if !$bin { </del> <ins> if !$bin { </ins> cargo.rustdocflag("--document-private-items"); <del> })? </del> <ins> } </ins> cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("-Zunstable-options");


} } <del> tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]); </del> <ins> tool_doc!( Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"], binary = false ); </ins> tool_doc!( Rustfmt, "rustfmt-nightly",


background: rgba(0, 0, 0, 0); } <del> code { </del> <ins> .docblock code { </ins> color: #ffb454; } h3 > code, h4 > code, h5 > code {


<ins> // The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to // check that the rule isn't applied on other "<code>" elements. goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html // We need to show the text, otherwise the colors aren't "computed" by the web browser. show-text: true // We set the theme to ayu. local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} // We reload to get the text appearing and the theme applied. reload: assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL) // It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum"). assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL) </ins>


#[doc(cfg(unix))] pub fn replaced_function() {} <ins> /// Some doc with `code`! </ins> pub enum AnEnum { WithVariants { and: usize, sub: usize, variants: usize }, }


<del> use crate::mem::{size_of, transmute_copy}; use crate::ptr::write_bytes; </del> pub(super) trait SpecFill<T> { fn spec_fill(&mut self, value: T); }


impl<T: Copy> SpecFill<T> for [T] { fn spec_fill(&mut self, value: T) { <del> if size_of::<T>() == 1 { // SAFETY: The size_of check above ensures that values are 1 byte wide, as required // for the transmute and write_bytes unsafe { let value: u8 = transmute_copy(&value); write_bytes(self.as_mut_ptr(), value, self.len()); } } else { for item in self.iter_mut() { *item = value; } </del> <ins> for item in self.iter_mut() { *item = value; </ins> } } }


use core::cell::Cell; use core::cmp::Ordering; <ins> use core::mem::MaybeUninit; </ins> use core::result::Result::{Err, Ok}; #[test]


assert_eq!(x.get(), 1); } <ins> #[test] fn test_slice_fill_with_uninit() { // This should not UB. See #87891 let mut a = [MaybeUninit::<u8>::uninit(); 10]; a.fill(MaybeUninit::uninit()); } </ins>


// of a macro that is not vendored by Rust and included in the toolchain. // See https://github.com/rust-analyzer/rust-analyzer/issues/6038. <ins> // On certain platforms right now the "main modules" modules that are // documented don't compile (missing things in `libc` which is empty), // so just omit them with an empty module and add the "unstable" attribute. // Unix, linux, wasi and windows are handled a bit differently. </ins> #[cfg(all( doc, <del> not(any( </del> <ins> any( </ins> all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") <del> )) </del> <ins> ) </ins> ))] <del> #[path = "."] mod doc { // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi` // modules as these are the "main modules" that are used across platforms, // so these modules are enabled when `cfg(doc)` is set. // This should help show platform-specific functionality in a hopefully cross-platform // way in the documentation. pub mod unix; pub mod linux; pub mod wasi; pub mod windows; } </del> <ins> #[unstable(issue = "none", feature = "std_internals")] pub mod unix {} </ins> #[cfg(all( doc, any(


all(target_vendor = "fortanix", target_env = "sgx") ) ))] <del> mod doc { // On certain platforms right now the "main modules" modules that are // documented don't compile (missing things in `libc` which is empty), // so just omit them with an empty module. #[unstable(issue = "none", feature = "std_internals")] pub mod unix {} #[unstable(issue = "none", feature = "std_internals")] pub mod linux {} #[unstable(issue = "none", feature = "std_internals")] pub mod wasi {} #[unstable(issue = "none", feature = "std_internals")] pub mod windows {} } #[cfg(doc)] #[stable(feature = "os", since = "1.0.0")] pub use doc::*; #[cfg(not(doc))] #[path = "."] mod imp { // If we're not documenting std then we only expose modules appropriate for the // current platform. #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub mod fortanix_sgx; #[cfg(target_os = "hermit")] #[path = "hermit/mod.rs"] pub mod unix; </del> <ins> #[unstable(issue = "none", feature = "std_internals")] pub mod linux {} #[cfg(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) ))] #[unstable(issue = "none", feature = "std_internals")] pub mod wasi {} #[cfg(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) ))] #[unstable(issue = "none", feature = "std_internals")] pub mod windows {} </ins> <del> #[cfg(target_os = "android")] pub mod android; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] pub mod emscripten; #[cfg(target_os = "espidf")] pub mod espidf; #[cfg(target_os = "freebsd")] pub mod freebsd; #[cfg(target_os = "fuchsia")] pub mod fuchsia; #[cfg(target_os = "haiku")] pub mod haiku; #[cfg(target_os = "illumos")] pub mod illumos; #[cfg(target_os = "ios")] pub mod ios; #[cfg(target_os = "l4re")] pub mod linux; #[cfg(target_os = "linux")] pub mod linux; #[cfg(target_os = "macos")] pub mod macos; #[cfg(target_os = "netbsd")] pub mod netbsd; #[cfg(target_os = "openbsd")] pub mod openbsd; #[cfg(target_os = "redox")] pub mod redox; #[cfg(target_os = "solaris")] pub mod solaris; #[cfg(unix)] pub mod unix; </del> <ins> // unix #[cfg(not(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] #[cfg(target_os = "hermit")] #[path = "hermit/mod.rs"] pub mod unix; #[cfg(not(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] #[cfg(all(not(target_os = "hermit"), any(unix, doc)))] pub mod unix; </ins> <del> #[cfg(target_os = "vxworks")] pub mod vxworks; </del> <ins> // linux #[cfg(not(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] #[cfg(any(target_os = "linux", target_os = "l4re", doc))] pub mod linux; </ins> <del> #[cfg(target_os = "wasi")] pub mod wasi; </del> <ins> // wasi #[cfg(not(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] #[cfg(any(target_os = "wasi", doc))] pub mod wasi; </ins> <del> #[cfg(windows)] pub mod windows; } #[cfg(not(doc))] #[stable(feature = "os", since = "1.0.0")] pub use imp::*; </del> <ins> // windows #[cfg(not(all( doc, any( all(target_arch = "wasm32", not(target_os = "wasi")), all(target_vendor = "fortanix", target_env = "sgx") ) )))] #[cfg(any(windows, doc))] pub mod windows; // Others. #[cfg(target_os = "android")] pub mod android; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] pub mod emscripten; #[cfg(target_os = "espidf")] pub mod espidf; #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] pub mod fortanix_sgx; #[cfg(target_os = "freebsd")] pub mod freebsd; #[cfg(target_os = "fuchsia")] pub mod fuchsia; #[cfg(target_os = "haiku")] pub mod haiku; #[cfg(target_os = "illumos")] pub mod illumos; #[cfg(target_os = "ios")] pub mod ios; #[cfg(target_os = "macos")] pub mod macos; #[cfg(target_os = "netbsd")] pub mod netbsd; #[cfg(target_os = "openbsd")] pub mod openbsd; #[cfg(target_os = "redox")] pub mod redox; #[cfg(target_os = "solaris")] pub mod solaris; #[cfg(target_os = "vxworks")] pub mod vxworks; </ins> #[cfg(any(unix, target_os = "wasi", doc))] mod fd;


pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"]; <del> pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs", "PermissionsExt", "from_mode"]; </del> <ins> pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"]; </ins> pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"]; pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];


//! normal visitor, which just walks the entire body in one shot, the //! `ExprUseVisitor` determines how expressions are being used. <ins> use hir::def::DefKind; </ins> // Export these here so that Clippy can use them. pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};


use rustc_infer::infer::InferCtxt; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; <del> use rustc_middle::ty::{self, adjustment, TyCtxt}; </del> <ins> use rustc_middle::ty::{self, adjustment, Ty, TyCtxt}; </ins> use rustc_target::abi::VariantIdx; use std::iter;


needs_to_be_read = true; } } <del> PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check // whether the Variant is a MultiVariant or a SingleVariant. We only want // to borrow discr if it is a MultiVariant. // If it is a SingleVariant and creates a binding we will handle that when // this callback gets called again. // Get the type of the Place after all projections have been applied let place_ty = place.place.ty(); if let ty::Adt(def, _) = place_ty.kind() { if def.variants.len() > 1 { </del> <ins> PatKind::Path(qpath) => { // A `Path` pattern is just a name like `Foo`. This is either a // named constant or else it refers to an ADT variant let res = self.mc.typeck_results.qpath_res(qpath, pat.hir_id); match res { Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { // Named constants have to be equated with the value // being matched, so that's a read of the value being matched. // // FIXME: We don't actually  reads for ZSTs. </ins> needs_to_be_read = true; } <del> } else { // If it is not ty::Adt, then it should be read needs_to_be_read = true; </del> <ins> _ => { // Otherwise, this is a struct/enum variant, and so it's // only a read if we need to read the discriminant. needs_to_be_read |= is_multivariant_adt(place.place.ty()); } </ins> } } <ins> PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { // For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching // against a multivariant enum or struct. In that case, we have to read // the discriminant. Otherwise this kind of pattern doesn't actually // read anything (we'll get invoked for the `...`, which may indeed // perform some reads). let place_ty = place.place.ty(); needs_to_be_read |= is_multivariant_adt(place_ty); } </ins> PatKind::Lit(_) | PatKind::Range(..) => { // If the PatKind is a Lit or a Range then we want // to borrow discr.


} } } <ins> fn is_multivariant_adt(ty: Ty<'tcx>) -> bool { if let ty::Adt(def, _) = ty.kind() { def.variants.len() > 1 } else { false } } </ins>


<ins> // edition:2021 #[derive(Copy, Clone, PartialEq, Eq)] pub struct Opcode(pub u8); impl Opcode { pub const OP1: Opcode = Opcode(0x1); } pub fn example1(msg_type: Opcode) -> impl FnMut(&[u8]) { move |i| match msg_type { //~^ ERROR: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered Opcode::OP1 => unimplemented!(), } } #[derive(Copy, Clone, PartialEq, Eq)] pub struct Opcode2(Opcode); impl Opcode2 { pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); } pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { move |i| match msg_type { //~^ ERROR: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered Opcode2::OP2=> unimplemented!(), } } fn main() {} </ins>


<ins> error[E0004]: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered --> $DIR/issue-88331.rs:11:20 | LL | pub struct Opcode(pub u8); | -------------------------- `Opcode` defined here ... LL |     move |i| match msg_type { |                    ^^^^^^^^ patterns `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `Opcode` error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered --> $DIR/issue-88331.rs:27:20 | LL | pub struct Opcode2(Opcode); | --------------------------- `Opcode2` defined here ... LL |     move |i| match msg_type { |                    ^^^^^^^^ patterns `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `Opcode2` error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0004`. </ins>


use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::cast::CastTy; <del> use rustc_middle::ty::subst::GenericArgKind; </del> <ins> use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; </ins> use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; use rustc_span::{sym, Span, Symbol};


let fn_ty = func.ty(body, tcx); <del> let (mut callee, substs) = match *fn_ty.kind() { </del> <ins> let (mut callee, mut substs) = match *fn_ty.kind() { </ins> ty::FnDef(def_id, substs) => (def_id, substs), ty::FnPtr(_) => {


.iter() .find(|did| tcx.item_name(**did) == callee_name) { <ins> // using internal substs is ok here, since this is only // used for the `resolve` call below substs = InternalSubsts::identity_for_item(tcx, did); </ins> callee = did; } } <del> _ => { if !tcx.is_const_fn_raw(callee) { // At this point, it is only legal when the caller is marked with // #[default_method_body_is_const], and the callee is in the same // trait. let callee_trait = tcx.trait_of_item(callee); if callee_trait.is_some() { if tcx.has_attr(caller, sym::default_method_body_is_const) { if tcx.trait_of_item(caller) == callee_trait { nonconst_call_permission = true; } </del> <ins> _ if !tcx.is_const_fn_raw(callee) => { // At this point, it is only legal when the caller is marked with // #[default_method_body_is_const], and the callee is in the same // trait. let callee_trait = tcx.trait_of_item(callee); if callee_trait.is_some() { if tcx.has_attr(caller, sym::default_method_body_is_const) { if tcx.trait_of_item(caller) == callee_trait { nonconst_call_permission = true; </ins> } } <ins> } </ins> <del> if !nonconst_call_permission { self.check_op(ops::FnCallNonConst); return; } </del> <ins> if !nonconst_call_permission { self.check_op(ops::FnCallNonConst); return; </ins> } } <ins> _ => {} </ins> } // Resolve a trait method call to its concrete implementation, which may be in a


<ins> // build-pass #![feature(const_trait_impl)] trait Func<T> { type Output; fn call_once(self, arg: T) -> Self::Output; } struct Closure; impl const Func<&usize> for Closure { type Output = usize; fn call_once(self, arg: &usize) -> Self::Output { *arg } } enum Bug<T = [(); Closure.call_once(&0) ]> { V(T), } fn main() {} </ins>


<del> Subproject commit 7a2f1cadcd5120c44eda3596053de767cd8173a2 </del> <ins> Subproject commit 035933186957cf81c488261fb48a98bf523e8006 </ins>


//! Enforces the Rust effect system. Currently there is just one effect, /// `unsafe`. <del> use middle::ty::{ty_bare_fn, ty_closure, ty_ptr}; </del> use middle::ty; use middle::typeck::method_map; use util::ppaux; <del> use syntax::ast::{UnDeref, ExprCall, ExprInlineAsm, ExprMethodCall}; use syntax::ast::{ExprUnary, unsafe_fn, ExprPath}; </del> use syntax::ast; use syntax::codemap::Span; <del> use syntax::visit::{fk_item_fn, fk_method}; </del> use syntax::visit; <del> use syntax::visit::{Visitor,fn_kind}; use syntax::ast::{fn_decl,Block,NodeId,Expr}; </del> <ins> use syntax::visit::Visitor; </ins> #[deriving(Eq)] enum UnsafeContext {


UnsafeBlock(ast::NodeId), } <del> struct Context { /// The method map. method_map: method_map, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, } </del> fn type_is_unsafe_function(ty: ty::t) -> bool { match ty::get(ty).sty { <del> ty_bare_fn(ref f) => f.purity == unsafe_fn, ty_closure(ref f) => f.purity == unsafe_fn, </del> <ins> ty::ty_bare_fn(ref f) => f.purity == ast::unsafe_fn, ty::ty_closure(ref f) => f.purity == ast::unsafe_fn, </ins> _ => false, } } struct EffectCheckVisitor { tcx: ty::ctxt, <del> context: @mut Context, </del> <ins> /// The method map. method_map: method_map, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, </ins> } impl EffectCheckVisitor { fn require_unsafe(&mut self, span: Span, description: &str) { <del> match self.context.unsafe_context { </del> <ins> match self.unsafe_context { </ins> SafeContext => { // Report an error. self.tcx.sess.span_err(span,


UnsafeFn => {} } } <ins> fn check_str_index(&mut self, e: @ast::Expr) { let base_type = match e.node { ast::ExprIndex(_, base, _) => ty::node_id_to_type(self.tcx, base.id), _ => return }; debug2!("effect: checking index with base type {}", ppaux::ty_to_str(self.tcx, base_type)); match ty::get(base_type).sty { ty::ty_estr(*) => { self.tcx.sess.span_err(e.span, "modification of string types is not allowed"); } _ => {} } } </ins> } impl Visitor<()> for EffectCheckVisitor { <del> fn visit_fn(&mut self, fn_kind:&fn_kind, fn_decl:&fn_decl, block:&Block, span:Span, node_id:NodeId, _:()) { let (is_item_fn, is_unsafe_fn) = match *fn_kind { fk_item_fn(_, _, purity, _) => (true, purity == unsafe_fn), fk_method(_, _, method) => (true, method.purity == unsafe_fn), _ => (false, false), }; let old_unsafe_context = self.context.unsafe_context; if is_unsafe_fn { self.context.unsafe_context = UnsafeFn } else if is_item_fn { self.context.unsafe_context = SafeContext } </del> <ins> fn visit_fn(&mut self, fn_kind: &visit::fn_kind, fn_decl: &ast::fn_decl, block: &ast::Block, span: Span, node_id: ast::NodeId, _:()) { let (is_item_fn, is_unsafe_fn) = match *fn_kind { visit::fk_item_fn(_, _, purity, _) => (true, purity == ast::unsafe_fn), visit::fk_method(_, _, method) => (true, method.purity == ast::unsafe_fn), _ => (false, false), }; let old_unsafe_context = self.unsafe_context; if is_unsafe_fn { self.unsafe_context = UnsafeFn } else if is_item_fn { self.unsafe_context = SafeContext } </ins> <del> visit::walk_fn(self, fn_kind, fn_decl, block, span, node_id, ()); </del> <ins> visit::walk_fn(self, fn_kind, fn_decl, block, span, node_id, ()); </ins> <del> self.context.unsafe_context = old_unsafe_context </del> <ins> self.unsafe_context = old_unsafe_context </ins> } <del> fn visit_block(&mut self, block:&Block, _:()) { let old_unsafe_context = self.context.unsafe_context; let is_unsafe = match block.rules { ast::UnsafeBlock(*) => true, ast::DefaultBlock => false }; if is_unsafe && self.context.unsafe_context == SafeContext { self.context.unsafe_context = UnsafeBlock(block.id) } </del> <ins> fn visit_block(&mut self, block: &ast::Block, _:()) { let old_unsafe_context = self.unsafe_context; let is_unsafe = match block.rules { ast::UnsafeBlock(*) => true, ast::DefaultBlock => false }; if is_unsafe && self.unsafe_context == SafeContext { self.unsafe_context = UnsafeBlock(block.id) } </ins> <del> visit::walk_block(self, block, ()); </del> <ins> visit::walk_block(self, block, ()); </ins> <del> self.context.unsafe_context = old_unsafe_context </del> <ins> self.unsafe_context = old_unsafe_context </ins> } <del> fn visit_expr(&mut self, expr:@Expr, _:()) { match expr.node { ExprMethodCall(callee_id, _, _, _, _, _) => { let base_type = ty::node_id_to_type(self.tcx, callee_id); debug2!("effect: method call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); if type_is_unsafe_function(base_type) { self.require_unsafe(expr.span, "invocation of unsafe method") } </del> <ins> fn visit_expr(&mut self, expr: @ast::Expr, _:()) { match expr.node { ast::ExprMethodCall(callee_id, _, _, _, _, _) => { let base_type = ty::node_id_to_type(self.tcx, callee_id); debug2!("effect: method call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); if type_is_unsafe_function(base_type) { self.require_unsafe(expr.span, "invocation of unsafe method") </ins> } <del> ExprCall(base, _, _) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug2!("effect: call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); if type_is_unsafe_function(base_type) { self.require_unsafe(expr.span, "call to unsafe function") } </del> <ins> } ast::ExprCall(base, _, _) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug2!("effect: call case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); if type_is_unsafe_function(base_type) { self.require_unsafe(expr.span, "call to unsafe function") </ins> } <del> ExprUnary(_, UnDeref, base) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug2!("effect: unary case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); match ty::get(base_type).sty { ty_ptr(_) => { self.require_unsafe(expr.span, "dereference of unsafe pointer") } _ => {} </del> <ins> } ast::ExprUnary(_, ast::UnDeref, base) => { let base_type = ty::node_id_to_type(self.tcx, base.id); debug2!("effect: unary case, base type is {}", ppaux::ty_to_str(self.tcx, base_type)); match ty::get(base_type).sty { ty::ty_ptr(_) => { self.require_unsafe(expr.span, "dereference of unsafe pointer") </ins> } <ins> _ => {} </ins> } <del> ExprInlineAsm(*) => { self.require_unsafe(expr.span, "use of inline assembly") } ExprPath(*) => { match ty::resolve_expr(self.tcx, expr) { ast::DefStatic(_, true) => { self.require_unsafe(expr.span, "use of mutable static") } _ => {} </del> <ins> } ast::ExprAssign(base, _) | ast::ExprAssignOp(_, _, base, _) => { self.check_str_index(base); } ast::ExprAddrOf(ast::MutMutable, base) => { self.check_str_index(base); } ast::ExprInlineAsm(*) => { self.require_unsafe(expr.span, "use of inline assembly") } ast::ExprPath(*) => { match ty::resolve_expr(self.tcx, expr) { ast::DefStatic(_, true) => { self.require_unsafe(expr.span, "use of mutable static") </ins> } <ins> _ => {} </ins> } <del> _ => {} </del> } <ins> _ => {} } </ins> <del> visit::walk_expr(self, expr, ()); </del> <ins> visit::walk_expr(self, expr, ()); </ins> } } pub fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: &ast::Crate) { <del> let context = @mut Context { method_map: method_map, unsafe_context: SafeContext, }; </del> let mut visitor = EffectCheckVisitor { tcx: tcx, <del> context: context, </del> <ins> method_map: method_map, unsafe_context: SafeContext, </ins> }; visit::walk_crate(&mut visitor, crate, ());


<ins> // Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { let mut s = ~"test"; s[0] = 3; //~ ERROR: not allowed s[0] += 3; //~ ERROR: not allowed { let _a = &mut s[0]; //~ ERROR: not allowed } } </ins>


<del> // check-fail // edition:2021 // known-bug: #88908 // This should pass, but seems to run into a TAIT bug. #![feature(type_alias_impl_trait)] use std::future::Future; trait Stream { type Item; } struct Empty<T>(T); impl<T> Stream for Empty<T> { type Item = (); } fn empty<T>() -> Empty<T> { todo!() } trait X { type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a; type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a; fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>; } struct Y; impl X for Y { type LineStream<'a, Repr> = impl Stream<Item = Repr>; type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ; fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { async {empty()} } } fn main() {} </del>


<del> error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr` --> $DIR/issue-89008.rs:38:43 | LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { |                        ----               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr` |                        | |                        this type parameter | note: expected this to be `()` --> $DIR/issue-89008.rs:17:17 | LL |     type Item = (); |                 ^^ = note:   expected unit type `()` found type parameter `Repr` error: aborting due to previous error For more information about this error, try `rustc --explain E0271`. </del>


<ins> // check-pass // edition:2021 #![feature(type_alias_impl_trait)] use std::future::Future; use std::marker::PhantomData; trait Stream { type Item; } struct Empty<T> { _phantom: PhantomData<T>, } impl<T> Stream for Empty<T> { type Item = T; } trait X { type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a; type LineStreamFut<'a, Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a; fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr>; } struct Y; impl X for Y { type LineStream<'a, Repr> = impl Stream<Item = Repr>; type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>; fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { async { Empty { _phantom: PhantomData } } } } fn main() {} </ins>


} else if nanos >= MAX_NANOS_F64 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) } else if nanos < 0.0 { <del> Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) </del> <ins> Err(FromSecsError { kind: FromSecsErrorKind::Negative }) </ins> } else { let nanos = nanos as u128; Ok(Duration {


} else if nanos >= MAX_NANOS_F32 { Err(FromSecsError { kind: FromSecsErrorKind::Overflow }) } else if nanos < 0.0 { <del> Err(FromSecsError { kind: FromSecsErrorKind::Underflow }) </del> <ins> Err(FromSecsError { kind: FromSecsErrorKind::Negative }) </ins> } else { let nanos = nanos as u128; Ok(Duration {


impl FromSecsError { const fn description(&self) -> &'static str { match self.kind { <del> FromSecsErrorKind::NonFinite => { "got non-finite value when converting float to duration" } </del> <ins> FromSecsErrorKind::NonFinite => "non-finite value when converting float to duration", </ins> FromSecsErrorKind::Overflow => "overflow when converting float to duration", <del> FromSecsErrorKind::Underflow => "underflow when converting float to duration", </del> <ins> FromSecsErrorKind::Negative => "negative value when converting float to duration", </ins> } } }


#[derive(Debug, Clone, PartialEq, Eq)] enum FromSecsErrorKind { <del> // Value is not a finite value (either infinity or NaN). </del> <ins> // Value is not a finite value (either + or - infinity or NaN). </ins> NonFinite, // Value is too large to store in a `Duration`. Overflow, <del> // Value is less than `0.0`. Underflow, </del> <ins> // Value is negative. Negative, </ins> }


} } <ins> /// Converts inline const patterns. fn lower_inline_const( &mut self, anon_const: &'tcx hir::AnonConst, id: hir::HirId, span: Span, ) -> PatKind<'tcx> { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); // Evaluate early like we do in `lower_path`. let value = value.eval(self.tcx, self.param_env); match value.val { ConstKind::Param(_) => { self.errors.push(PatternError::ConstParamInPattern(span)); return PatKind::Wild; } ConstKind::Unevaluated(_) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); return PatKind::Wild; } _ => (), } *self.const_to_pat(value, id, span, false).kind } </ins> /// Converts literals, paths and negation of literals to patterns. /// The special case for negation exists to allow things like `-128_i8` /// which would overflow if we tried to evaluate `128_i8` and then negate /// afterwards. fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { <del> if let hir::ExprKind::Path(ref qpath) = expr.kind { *self.lower_path(qpath, expr.hir_id, expr.span).kind } else { let (lit, neg) = match expr.kind { hir::ExprKind::ConstBlock(ref anon_const) => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); if matches!(value.val, ConstKind::Param(_)) { let span = self.tcx.hir().span(anon_const.hir_id); self.errors.push(PatternError::ConstParamInPattern(span)); return PatKind::Wild; } return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; } hir::ExprKind::Lit(ref lit) => (lit, false), hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { let lit = match expr.kind { hir::ExprKind::Lit(ref lit) => lit, _ => span_bug!(expr.span, "not a literal: {:?}", expr), }; (lit, true) } _ => span_bug!(expr.span, "not a literal: {:?}", expr), }; let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, Err(LitToConstError::Reported) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), </del> <ins> let (lit, neg) = match expr.kind { hir::ExprKind::Path(ref qpath) => { return *self.lower_path(qpath, expr.hir_id, expr.span).kind; } hir::ExprKind::ConstBlock(ref anon_const) => { return self.lower_inline_const(anon_const, expr.hir_id, expr.span); } hir::ExprKind::Lit(ref lit) => (lit, false), hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { let lit = match expr.kind { hir::ExprKind::Lit(ref lit) => lit, _ => span_bug!(expr.span, "not a literal: {:?}", expr), }; (lit, true) </ins> } <ins> _ => span_bug!(expr.span, "not a literal: {:?}", expr), }; let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, Err(LitToConstError::Reported) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), </ins> } } }


#![allow(incomplete_features)] #![feature(inline_const_pat)] <ins> #![feature(generic_const_exprs)] </ins> // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter fn foo<const V: usize>() { <del> match 0 { const { V } => {}, //~^ ERROR const parameters cannot be referenced in patterns [E0158] _ => {}, } </del> <ins> match 0 { const { V } => {}, //~^ ERROR const parameters cannot be referenced in patterns [E0158] _ => {}, } } const fn f(x: usize) -> usize { x + 1 } fn bar<const V: usize>() where [(); f(V)]: { match 0 { const { f(V) } => {}, //~^ ERROR constant pattern depends on a generic parameter //~| ERROR constant pattern depends on a generic parameter _ => {}, } </ins> } fn main() { foo::<1>(); <ins> bar::<1>(); </ins> }


error[E0158]: const parameters cannot be referenced in patterns <del> --> $DIR/const-match-pat-generic.rs:8:11 </del> <ins> --> $DIR/const-match-pat-generic.rs:9:9 </ins> | <del> LL |     const { V } => {}, |           ^^^^^ </del> <ins> LL |         const { V } => {}, |         ^^^^^^^^^^^ </ins> <del> error: aborting due to previous error </del> <ins> error: constant pattern depends on a generic parameter --> $DIR/const-match-pat-generic.rs:21:9 | LL |         const { f(V) } => {}, |         ^^^^^^^^^^^^^^ error: constant pattern depends on a generic parameter --> $DIR/const-match-pat-generic.rs:21:9 | LL |         const { f(V) } => {}, |         ^^^^^^^^^^^^^^ error: aborting due to 3 previous errors </ins> For more information about this error, try `rustc --explain E0158`.


drop(linker); save_temp_bitcode(cgcx, &module, "lto.input"); <del> // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO. // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`. // This only works around the problem when codegen-units = 1. // Refer to the comments in the `optimize_thin_module` function for more details. let mut cu1 = ptr::null_mut(); let mut cu2 = ptr::null_mut(); unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) }; if !cu2.is_null() { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name); unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) }; save_temp_bitcode(cgcx, &module, "fat-lto-after-patch"); } </del> // Internalize everything below threshold to help strip out more modules and such. unsafe { let ptr = symbols_below_threshold.as_ptr();


// an error. let mut cu1 = ptr::null_mut(); let mut cu2 = ptr::null_mut(); <del> llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); </del> <ins> llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); </ins> if !cu2.is_null() { let msg = "multiple source DICompileUnits found"; return Err(write::llvm_err(&diag_handler, msg));


let _timer = cgcx .prof .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name()); <del> llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1); </del> <ins> llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); </ins> save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); }


len: usize, out_len: &mut usize, ) -> *const u8; <del> pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); </del> <ins> pub fn LLVMRustThinLTOGetDICompileUnit( M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void, ); pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); </ins> pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub fn LLVMRustLinkerAdd(


// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void <del> LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod, </del> <ins> LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, </ins> DICompileUnit **A, DICompileUnit **B) { Module *M = unwrap(Mod);


// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void <del> LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { </del> <ins> LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { </ins> Module *M = unwrap(Mod); // If the original source module didn't have a `DICompileUnit` then try to


<ins> // Caveat - gdb doesn't know about UTF-32 character encoding and will print a // rust char as only its numerical value. // min-lldb-version: 310 // min-gdb-version: 8.0 // no-prefer-dynamic // compile-flags:-g -C lto // gdb-command:run // gdbg-command:print 'basic_types_globals::B' // gdbr-command:print B // gdb-check:$1 = false // gdbg-command:print 'basic_types_globals::I' // gdbr-command:print I // gdb-check:$2 = -1 // gdbg-command:print 'basic_types_globals::C' // gdbr-command:print C // gdbg-check:$3 = 97 // gdbr-check:$3 = 97 // gdbg-command:print/d 'basic_types_globals::I8' // gdbr-command:print I8 // gdb-check:$4 = 68 // gdbg-command:print 'basic_types_globals::I16' // gdbr-command:print I16 // gdb-check:$5 = -16 // gdbg-command:print 'basic_types_globals::I32' // gdbr-command:print I32 // gdb-check:$6 = -32 // gdbg-command:print 'basic_types_globals::I64' // gdbr-command:print I64 // gdb-check:$7 = -64 // gdbg-command:print 'basic_types_globals::U' // gdbr-command:print U // gdb-check:$8 = 1 // gdbg-command:print/d 'basic_types_globals::U8' // gdbr-command:print U8 // gdb-check:$9 = 100 // gdbg-command:print 'basic_types_globals::U16' // gdbr-command:print U16 // gdb-check:$10 = 16 // gdbg-command:print 'basic_types_globals::U32' // gdbr-command:print U32 // gdb-check:$11 = 32 // gdbg-command:print 'basic_types_globals::U64' // gdbr-command:print U64 // gdb-check:$12 = 64 // gdbg-command:print 'basic_types_globals::F32' // gdbr-command:print F32 // gdb-check:$13 = 2.5 // gdbg-command:print 'basic_types_globals::F64' // gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] // N.B. These are `mut` only so they don't constant fold away. static mut B: bool = false; static mut I: isize = -1; static mut C: char = 'a'; static mut I8: i8 = 68; static mut I16: i16 = -16; static mut I32: i32 = -32; static mut I64: i64 = -64; static mut U: usize = 1; static mut U8: u8 = 100; static mut U16: u16 = 16; static mut U32: u32 = 32; static mut U64: u64 = 64; static mut F32: f32 = 2.5; static mut F64: f64 = 3.5; fn main() { _zzz(); // #break let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; } fn _zzz() {()} </ins>


<del> // Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values) // as its numerical value along with its associated ASCII char, there // doesn't seem to be any way around this. Also, gdb doesn't know // about UTF-32 character encoding and will print a rust char as only // its numerical value. </del> <ins> // Caveat - gdb doesn't know about UTF-32 character encoding and will print a // rust char as only its numerical value. </ins> // min-lldb-version: 310 <del> // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 </del> <ins> // min-gdb-version: 8.0 </ins> // compile-flags:-g // gdb-command:run


// gdbg-command:print 'basic_types_globals::C' // gdbr-command:print C // gdbg-check:$3 = 97 <del> // gdbr-check:$3 = 97 'a' </del> <ins> // gdbr-check:$3 = 97 </ins> // gdbg-command:print/d 'basic_types_globals::I8' // gdbr-command:print I8 // gdb-check:$4 = 68


}) .enumerate() .map(|(i, r)| match r { <del> Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)), Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)), </del> <ins> Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => { Err(TypeError::ArgumentSorts(exp_found, i)) } Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => { Err(TypeError::ArgumentMutability(i)) } </ins> r => r, }); Ok(ty::FnSig {


Ok(()) } <ins> #[instrument(level = "debug", skip(infcx))] </ins> fn extract_spans_for_error_reporting<'a, 'tcx>( infcx: &infer::InferCtxt<'a, 'tcx>, terr: &TypeError<'_>,


<ins> pub struct A; impl From<fn((), (), &())> for A { fn from(_: fn((), (), &mut ())) -> Self { //~^ error: method `from` has an incompatible type for trait loop {} } } pub struct B; impl From<fn((), (), u32)> for B { fn from(_: fn((), (), u64)) -> Self { //~^ error: method `from` has an incompatible type for trait loop {} } } fn main() {} </ins>


<ins> error[E0053]: method `from` has an incompatible type for trait --> $DIR/issue-90444.rs:3:16 | LL |     fn from(_: fn((), (), &mut ())) -> Self { |                ^^^^^^^^^^^^^^^^^^^ |                | |                types differ in mutability |                help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())` | = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A` found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A` error[E0053]: method `from` has an incompatible type for trait --> $DIR/issue-90444.rs:11:16 | LL |     fn from(_: fn((), (), u64)) -> Self { |                ^^^^^^^^^^^^^^^ |                | |                expected `u32`, found `u64` |                help: change the parameter type to match the trait: `fn((), (), u32)` | = note: expected fn pointer `fn(fn((), (), u32)) -> B` found fn pointer `fn(fn((), (), u64)) -> B` error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0053`. </ins>


pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) } <del> pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf { in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME) } </del> pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)


// Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. <del> let path = dep_graph_path_from(&sess.incr_comp_session_dir()); </del> <ins> let path = dep_graph_path(&sess); </ins> let report_incremental_info = sess.opts.debugging_opts.incremental_info; let expected_hash = sess.opts.dep_tracking_hash(false);


is bootstrapped and in general, some of the technical details of the build system. <del> ## Using rustbuild </del> <ins> Note that this README only covers internal information, not how to use the tool. Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information. </ins> <del> The rustbuild build system has a primary entry point, a top level `x.py` script: </del> <ins> [bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html </ins> <del> ```sh $ python ./x.py build ``` Note that if you're on Unix, you should be able to execute the script directly: ```sh $ ./x.py build ``` The script accepts commands, flags, and arguments to determine what to do: * `build` - a general purpose command for compiling code. Alone, `build` will bootstrap the entire compiler, and otherwise, arguments passed indicate what to build. For example: ``` # build the whole compiler ./x.py build --stage 2 # build the stage1 compiler ./x.py build # build stage0 libstd ./x.py build --stage 0 library/std # build a particular crate in stage0 ./x.py build --stage 0 library/test ``` If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps that belong to stage n or earlier: ``` # build stage 1, keeping old build products for stage 0 ./x.py build --keep-stage 0 ``` * `test` - a command for executing unit tests. Like the `build` command, this will execute the entire test suite by default, and otherwise, it can be used to select which test suite is run: ``` # run all unit tests ./x.py test # execute tool tests ./x.py test tidy # execute the UI test suite ./x.py test tests/ui # execute only some tests in the UI test suite ./x.py test tests/ui --test-args substring-of-test-name # execute tests in the standard library in stage0 ./x.py test --stage 0 library/std # execute tests in the core and standard library in stage0, # without running doc tests (thus avoid depending on building the compiler) ./x.py test --stage 0 --no-doc library/core library/std </del> <ins> ## Introduction </ins> <del> # execute all doc tests ./x.py test src/doc ``` </del> <ins> The build system defers most of the complicated logic managing invocations of rustc and rustdoc to Cargo itself. However, moving through various stages and copying artifacts is still necessary for it to do. Each time rustbuild is invoked, it will iterate through the list of predefined steps and execute each serially in turn if it matches the paths passed or is a default rule. For each step rustbuild relies on the step internally being incremental and parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded to appropriate test harnesses and such. </ins> <del> * `doc` - a command for building documentation. Like above, can take arguments for what to document. ## Configuring rustbuild rustbuild offers a TOML-based configuration system with a `config.toml` file. An example of this configuration can be found at `config.toml.example`, and the configuration file can also be passed as `--config path/to/config.toml` if the build system is being invoked manually (via the python script). You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it. Finally, rustbuild makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment variables. [cc-rs crate]: https://github.com/alexcrichton/cc-rs [env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables ## Build stages </del> <ins> ## Build phases </ins> The rustbuild build system goes through a few phases to actually build the compiler. What actually happens when you invoke rustbuild is: <del> 1. The entry point script, `x.py` is run. This script is responsible for downloading the stage0 compiler/Cargo binaries, and it then compiles the build system itself (this folder). Finally, it then invokes the actual `bootstrap` binary build system. </del> <ins> 1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems, `x.py` cross-platform) is run. This script is responsible for downloading the stage0 compiler/Cargo binaries, and it then compiles the build system itself (this folder). Finally, it then invokes the actual `bootstrap` binary build system. </ins> 2. In Rust, `bootstrap` will slurp up all configuration, perform a number of sanity checks (whether compilers exist, for example), and then start building the stage0 artifacts.


The goal of each stage is to (a) leverage Cargo as much as possible and failing that (b) leverage Rust as much as possible! <del> ## Incremental builds You can configure rustbuild to use incremental compilation with the `--incremental` flag: ```sh $ ./x.py build --incremental ``` The `--incremental` flag will store incremental compilation artifacts in `build/<host>/stage0-incremental`. Note that we only use incremental compilation for the stage0 -> stage1 compilation -- this is because the stage1 compiler is changing, and we don't try to cache and reuse incremental artifacts across different versions of the compiler. You can always drop the `--incremental` to build as normal (but you will still be using the local nightly as your bootstrap). </del> ## Directory Layout This build system houses all output under the `build` directory, which looks


# system will link (using hard links) output from stageN-{std,rustc} into # each of these directories. # <del> # In theory, there is no extra build output in these directories. </del> <ins> # In theory these are working rustc sysroot directories, meaning there is # no extra build output in these directories. </ins> stage1/ stage2/ stage3/ ``` <del> ## Cargo projects The current build is unfortunately not quite as simple as `cargo build` in a directory, but rather the compiler is split into three different Cargo projects: * `library/std` - the standard library * `library/test` - testing support, depends on libstd * `compiler/rustc` - the actual compiler itself Each "project" has a corresponding Cargo.lock file with all dependencies, and this means that building the compiler involves running Cargo three times. The structure here serves two goals: 1. Facilitating dependencies coming from crates.io. These dependencies don't depend on `std`, so libstd is a separate project compiled ahead of time before the actual compiler builds. 2. Splitting "host artifacts" from "target artifacts". That is, when building code for an arbitrary target, you don't need the entire compiler, but you'll end up needing libraries like libtest that depend on std but also want to use crates.io dependencies. Hence, libtest is split out as its own project that is sequenced after `std` but before `rustc`. This project is built for all targets. There is some loss in build parallelism here because libtest can be compiled in parallel with a number of rustc artifacts, but in theory, the loss isn't too bad! ## Build tools We've actually got quite a few tools that we use in the compiler's build system and for testing. To organize these, each tool is a project in `src/tools` with a corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having independent `Cargo.lock` files) and do not currently explicitly depend on the compiler or standard library. Compiling each tool is sequenced after the appropriate libstd/libtest/librustc compile above. </del> ## Extending rustbuild <del> So, you'd like to add a feature to the rustbuild build system or just fix a bug. Great! One of the major motivational factors for moving away from `make` is that Rust is in theory much easier to read, modify, and write. If you find anything excessively confusing, please open an issue on this, and we'll try to get it documented or simplified, pronto. </del> <ins> When you use the bootstrap system, you'll call it through the entry point script (`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. `bootstrap` has a difficult problem: it is written in Rust, but yet it is run before the Rust compiler is built! To work around this, there are two components of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py` is what gets run by entry point script. It takes care of downloading the `stage0` compiler, which will then build the bootstrap binary written in Rust. </ins> <del> First up, you'll probably want to read over the documentation above, as that'll give you a high level overview of what rustbuild is doing. You also probably want to play around a bit yourself by just getting it up and running before you dive too much into the actual build system itself. </del> <ins> Because there are two separate codebases behind `x.py`, they need to be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary parse `config.toml` and read the same command line arguments. `bootstrap.py` keeps these in sync by setting various environment variables, and the programs sometimes have to add arguments that are explicitly ignored, to be read by the other. </ins> <del> After that, each module in rustbuild should have enough documentation to keep you up and running. Some general areas that you may be interested in modifying are: </del> <ins> Some general areas that you may be interested in modifying are: </ins> * Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of other tools.


Changes that do not affect contributors to the compiler or users building rustc from source don't need an update to `VERSION`. <del> If you have any questions, feel free to reach out on the `#t-infra` channel in the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When you encounter bugs, please file issues on the rust-lang/rust issue tracker. </del> <ins> If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs, please file issues on the [Rust issue tracker][rust-issue-tracker]. </ins> <del> [rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra </del> <ins> [rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap [rust-issue-tracker]: https://github.com/rust-lang/rust/issues </ins>


//!   crates.io and Cargo. //! * A standard interface to build across all platforms, including MSVC //! <del> //! ## Architecture //! //! The build system defers most of the complicated logic managing invocations //! of rustc and rustdoc to Cargo itself. However, moving through various stages //! and copying artifacts is still necessary for it to do. Each time rustbuild //! is invoked, it will iterate through the list of predefined steps and execute //! each serially in turn if it matches the paths passed or is a default rule. //! For each step rustbuild relies on the step internally being incremental and //! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded //! to appropriate test harnesses and such. //! //! Most of the "meaty" steps that matter are backed by Cargo, which does indeed //! have its own parallelism and incremental management. Later steps, like //! tests, aren't incremental and simply run the entire suite currently. //! However, compiletest itself tries to avoid running tests when the artifacts //! that are involved (mainly the compiler) haven't changed. //! //! When you execute `x.py build`, the steps executed are: //! //! * First, the python script is run. This will automatically download the //!   stage0 rustc and cargo according to `src/stage0.json`, or use the cached //!   versions if they're available. These are then used to compile rustbuild //!   itself (using Cargo). Finally, control is then transferred to rustbuild. //! //! * Rustbuild takes over, performs sanity checks, probes the environment, //!   reads configuration, and starts executing steps as it reads the command //!   line arguments (paths) or going through the default rules. //! //!   The build output will be something like the following: //! //!   Building stage0 std artifacts //!   Copying stage0 std //!   Building stage0 test artifacts //!   Copying stage0 test //!   Building stage0 compiler artifacts //!   Copying stage0 rustc //!   Assembling stage1 compiler //!   Building stage1 std artifacts //!   Copying stage1 std //!   Building stage1 test artifacts //!   Copying stage1 test //!   Building stage1 compiler artifacts //!   Copying stage1 rustc //!   Assembling stage2 compiler //!   Uplifting stage1 std //!   Uplifting stage1 test //!   Uplifting stage1 rustc //! //! Let's disect that a little: //! //! ## Building stage0 {std,test,compiler} artifacts //! //! These steps use the provided (downloaded, usually) compiler to compile the //! local Rust source into libraries we can use. //! //! ## Copying stage0 {std,test,rustc} //! //! This copies the build output from Cargo into //! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's //! documentation should be expanded -- the information already here may be //! incorrect. //! //! ## Assembling stage1 compiler //! //! This copies the libraries we built in "building stage0 ... artifacts" into //! the stage1 compiler's lib directory. These are the host libraries that the //! compiler itself uses to run. These aren't actually used by artifacts the new //! compiler generates. This step also copies the rustc and rustdoc binaries we //! generated into build/$HOST/stage/bin. //! //! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have //! any libraries to link built binaries or libraries to. The next 3 steps will //! provide those libraries for it; they are mostly equivalent to constructing //! the stage1/bin compiler so we don't go through them individually. //! //! ## Uplifting stage1 {std,test,rustc} //! //! This step copies the libraries from the stage1 compiler sysroot into the //! stage2 compiler. This is done to avoid rebuilding the compiler; libraries //! we'd build in this step should be identical (in function, if not necessarily //! identical on disk) so there's no need to recompile the compiler again. Note //! that if you want to, you can enable the full-bootstrap option to change this //! behavior. //! //! Each step is driven by a separate Cargo project and rustbuild orchestrates //! copying files between steps and otherwise preparing for Cargo to run. //! </del> //! ## Further information //! //! More documentation can be found in each respective module below, and you can


<ins> fn main() { 2: n([u8; || 1]) //~^ ERROR cannot find type `n` in this scope //~| ERROR mismatched types } </ins>


<ins> error[E0412]: cannot find type `n` in this scope --> $DIR/issue-90871.rs:2:8 | LL |     2: n([u8; || 1]) |        ^ expecting a type here because of type ascription error[E0308]: mismatched types --> $DIR/issue-90871.rs:2:15 | LL |     2: n([u8; || 1]) |               ^^^^ expected `usize`, found closure | = note: expected type `usize` found closure `[closure@$DIR/issue-90871.rs:2:15: 2:17]` help: use parentheses to call this closure | LL |     2: n([u8; (|| 1)()]) |               +    +++ error: aborting due to 2 previous errors Some errors have detailed explanations: E0308, E0412. For more information about an error, try `rustc --explain E0308`. </ins>


use crate::meth; use crate::traits::*; use rustc_middle::ty::{self, Ty}; <ins> use rustc_target::abi::WrappingRange; </ins> pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx,


} match t.kind() { ty::Dynamic(..) => { <del> // load size/align from vtable </del> <ins> // Load size/align from vtable. </ins> let vtable = info.unwrap(); <del> ( meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) .get_usize(bx, vtable), meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) .get_usize(bx, vtable), ) </del> <ins> let size = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) .get_usize(bx, vtable); let align = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) .get_usize(bx, vtable); // Alignment is always nonzero. bx.range_metadata(align, WrappingRange { start: 1, end: !0 }); (size, align) </ins> } ty::Slice(_) | ty::Str => { let unit = layout.field(bx, 0);


<ins> // compile-flags: -O #![crate_type = "lib"] // This test checks that we annotate alignment loads from vtables with nonzero range metadata, // and that this allows LLVM to eliminate redundant `align >= 1` checks. pub trait Trait { fn f(&self); } pub struct WrapperWithAlign1<T: ?Sized> { x: u8, y: T } pub struct WrapperWithAlign2<T: ?Sized> { x: u16, y: T } pub struct Struct<W: ?Sized> { _field: i8, dst: W, } // CHECK-LABEL: @eliminates_runtime_check_when_align_1 #[no_mangle] pub fn eliminates_runtime_check_when_align_1( x: &Struct<WrapperWithAlign1<dyn Trait>> ) -> &WrapperWithAlign1<dyn Trait> { // CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]] // CHECK-NOT: icmp // CHECK-NOT: select // CHECK: ret &x.dst } // CHECK-LABEL: @does_not_eliminate_runtime_check_when_align_2 #[no_mangle] pub fn does_not_eliminate_runtime_check_when_align_2( x: &Struct<WrapperWithAlign2<dyn Trait>> ) -> &WrapperWithAlign2<dyn Trait> { // CHECK: [[X0:%[0-9]+]] = load [[USIZE]], {{.+}} !range [[RANGE_META]] // CHECK: [[X1:%[0-9]+]] = icmp {{.+}} [[X0]] // CHECK: [[X2:%[0-9]+]] = select {{.+}} [[X1]] // CHECK: ret &x.dst } // CHECK: [[RANGE_META]] = !{[[USIZE]] 1, [[USIZE]] 0} </ins>


// (e.g. the `bootimage` crate). for tool in LLVM_TOOLS { let tool_exe = exe(tool, target_compiler.host); <del> builder.copy(&llvm_bin_dir.join(&tool_exe), &libdir_bin.join(&tool_exe)); </del> <ins> let src_path = llvm_bin_dir.join(&tool_exe); // When using `donwload-ci-llvm`, some of the tools // may not exist, so skip trying to copy them. if src_path.exists() { builder.copy(&src_path, &libdir_bin.join(&tool_exe)); } </ins> } } }


impl<CTX> HashStable<CTX> for InferTy { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { use InferTy::*; <ins> discriminant(self).hash_stable(ctx, hasher); </ins> match self { TyVar(v) => v.as_u32().hash_stable(ctx, hasher), IntVar(v) => v.index.hash_stable(ctx, hasher),


<ins> // check-pass // incremental struct Struct<T>(T); impl<T> std::ops::Deref for Struct<T> { type Target = dyn Fn(T); fn deref(&self) -> &Self::Target { unimplemented!() } } fn main() { let f = Struct(Default::default()); f(0); f(0); } </ins>


* other tasks wishing to access the data will block until the closure * finishes running. * <del> * The reason this function is 'unsafe' is because it is possible to * construct a circular reference among multiple Arcs by mutating the * underlying data. This creates potential for deadlock, but worse, this * will guarantee a memory leak of all involved Arcs. Using MutexArcs * inside of other Arcs is safe in absence of circular references. * </del> * If you wish to nest MutexArcs, one strategy for ensuring safety at * runtime is to add a "nesting level counter" inside the stored data, and * when traversing the arcs, assert that they monotonically decrease.


* blocked on the mutex) will also fail immediately. */ #[inline] <del> pub unsafe fn unsafe_access<U>(&self, blk: |x: &mut T| -> U) -> U { </del> <ins> pub fn access<U>(&self, blk: |x: &mut T| -> U) -> U { </ins> let state = self.x.get(); <del> // Borrowck would complain about this if the function were // not already unsafe. See borrow_rwlock, far below. (&(*state).lock).lock(|| { check_poison(true, (*state).failed); let _z = PoisonOnFail::new(&mut (*state).failed); blk(&mut (*state).data) }) </del> <ins> unsafe { // Borrowck would complain about this if the code were // not already unsafe. See borrow_rwlock, far below. (&(*state).lock).lock(|| { check_poison(true, (*state).failed); let _z = PoisonOnFail::new(&mut (*state).failed); blk(&mut (*state).data) }) } </ins> } <del> /// As unsafe_access(), but with a condvar, as sync::mutex.lock_cond(). </del> <ins> /// As access(), but with a condvar, as sync::mutex.lock_cond(). </ins> #[inline] <del> pub unsafe fn unsafe_access_cond<U>(&self, blk: |x: &mut T, c: &Condvar| -> U) -> U { </del> <ins> pub fn access_cond<U>(&self, blk: |x: &mut T, c: &Condvar| -> U) -> U { </ins> let state = self.x.get(); <del> (&(*state).lock).lock_cond(|cond| { check_poison(true, (*state).failed); let _z = PoisonOnFail::new(&mut (*state).failed); blk(&mut (*state).data, &Condvar {is_mutex: true, failed: &(*state).failed, cond: cond }) }) } } impl<T:Freeze + Send> MutexArc<T> { /** * As unsafe_access. * * The difference between access and unsafe_access is that the former * forbids mutexes to be nested. While unsafe_access can be used on * MutexArcs without freezable interiors, this safe version of access * requires the Freeze bound, which prohibits access on MutexArcs which * might contain nested MutexArcs inside. * * The purpose of this is to offer a safe implementation of MutexArc to be * used instead of RWArc in cases where no readers are needed and slightly * better performance is required. * * Both methods have the same failure behaviour as unsafe_access and * unsafe_access_cond. */ #[inline] pub fn access<U>(&self, blk: |x: &mut T| -> U) -> U { unsafe { self.unsafe_access(blk) } } /// As unsafe_access_cond but safe and Freeze. #[inline] pub fn access_cond<U>(&self, blk: |x: &mut T, c: &Condvar| -> U) -> U { unsafe { self.unsafe_access_cond(blk) } </del> <ins> unsafe { (&(*state).lock).lock_cond(|cond| { check_poison(true, (*state).failed); let _z = PoisonOnFail::new(&mut (*state).failed); blk(&mut (*state).data, &Condvar {is_mutex: true, failed: &(*state).failed, cond: cond }) }) } </ins> } }


impl<T:Clone+Send+Freeze> Clone for CowArc<T> { /// Duplicate a Copy-on-write Arc. See arc::clone for more details. <del> #[inline] </del> fn clone(&self) -> CowArc<T> { CowArc { x: self.x.clone() } }


} #[test] <del> fn test_unsafe_mutex_arc_nested() { unsafe { // Tests nested mutexes and access // to underlaying data. let arc = ~MutexArc::new(1); let arc2 = ~MutexArc::new(*arc); task::spawn(proc() { (*arc2).unsafe_access(|mutex| { (*mutex).access(|one| { assert!(*one == 1); }) </del> <ins> fn test_mutex_arc_nested() { // Tests nested mutexes and access // to underlaying data. let arc = ~MutexArc::new(1); let arc2 = ~MutexArc::new(*arc); task::spawn(proc() { (*arc2).access(|mutex| { (*mutex).access(|one| { assert!(*one == 1); </ins> }) <del> }); } </del> <ins> }) }); </ins> } #[test]


<del> // Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. extern crate sync; use std::task; use sync::MutexArc; fn test_mutex_arc_nested() { let arc = ~MutexArc::new(1); let arc2 = ~MutexArc::new(*arc); task::spawn(proc() { (*arc2).access(|mutex| { //~ ERROR instantiating a type parameter with an incompatible type }) }); } fn main() {} </del>


}); assert!(actually_finished.load(Ordering::Relaxed)); } <ins> #[test] fn test_scoped_threads_nll() { // this is mostly a *compilation test* for this exact function: fn foo(x: &u8) { thread::scope(|s| { s.spawn(|| drop(x)); }); } // let's also run it for good measure let x = 42_u8; foo(&x); } </ins>


), .. }) => { <del> // We have a situation like `while Some(0) = value.get(0) {`, where `while let` // was more likely intended. err.span_suggestion_verbose( expr.span.shrink_to_lo(), "you might have meant to use pattern destructuring", "let ".to_string(), Applicability::MachineApplicable, ); </del> <ins> // Check if our lhs is a child of the condition of a while loop let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| { self.tcx.hir().find_parent_node(*id) }) .take_while(|id| *id != parent) .any(|id| id == expr.hir_id); // if it is, then we have a situation like `while Some(0) = value.get(0) {`, // where `while let` was more likely intended. if expr_is_ancestor { err.span_suggestion_verbose( expr.span.shrink_to_lo(), "you might have meant to use pattern destructuring", "let ".to_string(), Applicability::MachineApplicable, ); } </ins> break; } hir::Node::Item(_)


<ins> fn main() { while let 1 = 1 { vec![].last_mut().unwrap() = 3_u8; //~^ ERROR invalid left-hand side of assignment } } </ins>


<ins> error[E0070]: invalid left-hand side of assignment --> $DIR/issue-93486.rs:3:36 | LL |         vec![].last_mut().unwrap() = 3_u8; |         -------------------------- ^ |         | |         cannot assign to this expression error: aborting due to previous error For more information about this error, try `rustc --explain E0070`. </ins>


&self, tcx: TyCtxt<'_>, ident: Ident, <ins> // Sorted in order of what kinds to look at </ins> kinds: &[AssocKind], parent_def_id: DefId, ) -> Option<&ty::AssocItem> { <del> self.filter_by_name_unhygienic(ident.name) .filter(|item| kinds.contains(&item.kind)) .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) </del> <ins> kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id)) </ins> } /// Returns the associated item with the given name in the given `Namespace`, if one exists.


.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id) .is_some() } <del> fn trait_defines_associated_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { </del> <ins> fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { </ins> self.tcx() .associated_items(trait_def_id) <del> .find_by_name_and_kinds( self.tcx(), assoc_name, &[ty::AssocKind::Type, ty::AssocKind::Const], trait_def_id, ) </del> <ins> .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id) </ins> .is_some() }


// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. <del> let assoc_item = tcx .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) .find(|i| { (i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const) && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident }) </del> <ins> let find_item_of_kind = |kind| { tcx.associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) }; let assoc_item = find_item_of_kind(ty::AssocKind::Type) .or_else(|| find_item_of_kind(ty::AssocKind::Const)) </ins> .expect("missing associated type"); if !assoc_item.vis.is_accessible_from(def_scope, tcx) {


I: Iterator<Item = ty::PolyTraitRef<'tcx>>, { let mut matching_candidates = all_candidates() <del> .filter(|r| self.trait_defines_associated_named(r.def_id(), assoc_name)); let bound = match matching_candidates.next() { Some(bound) => bound, None => { </del> <ins> .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); let mut const_candidates = all_candidates() .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name)); let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { (Some(bound), _) => (bound, matching_candidates.next()), (None, Some(bound)) => (bound, const_candidates.next()), (None, None) => { </ins> self.complain_about_assoc_type_not_found( all_candidates, &ty_param_name(),


return Err(ErrorReported); } }; debug!("one_bound_for_assoc_type: bound = {:?}", bound); <del> if let Some(bound2) = matching_candidates.next() { </del> <ins> if let Some(bound2) = next_cand { </ins> debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); let is_equality = is_equality();


// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. <del> let item = tcx .associated_items(trait_did) .in_definition_order() .find(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident }) .expect("missing associated type"); </del> <ins> let item = tcx.associated_items(trait_did).in_definition_order().find(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident }); // Assume that if it's not matched, there must be a const defined with the same name // but it was used in a type position. let Some(item) = item else { let msg = format!("found associated const `{assoc_ident}` when type was expected"); tcx.sess.struct_span_err(span, &msg).emit(); return Err(ErrorReported); }; </ins> let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); let ty = self.normalize_ty(span, ty);


<ins> // Checking that none of these ICE, which was introduced in // https://github.com/rust-lang/rust/issues/93553 trait Foo { type Bar; } trait Baz: Foo { const Bar: Self::Bar; } trait Baz2: Foo { const Bar: u32; fn foo() -> Self::Bar; } trait Baz3 { const BAR: usize; const QUX: Self::BAR; //~^ ERROR found associated const } fn main() {} </ins>


<ins> error: found associated const `BAR` when type was expected --> $DIR/shadowed-const.rs:19:14 | LL |   const QUX: Self::BAR; |              ^^^^^^^^^ error: aborting due to previous error </ins>


} /// Iterates over the language items in the given crate. <del> fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { tcx.arena.alloc_from_iter( self.root .lang_items .decode(self) .map(|(def_index, index)| (self.local_def_id(def_index), index)), ) </del> <ins> fn get_lang_items(self) -> impl Iterator<Item = (DefId, usize)> + 'a { self.root .lang_items .decode(self) .map(move |(def_index, index)| (self.local_def_id(def_index), index)) </ins> } /// Iterates over the diagnostic items in the given crate.


tcx.arena.alloc_slice(&result) } defined_lib_features => { cdata.get_lib_features(tcx) } <del> defined_lang_items => { cdata.get_lang_items(tcx) } </del> <ins> defined_lang_items => { tcx.arena.alloc_from_iter(cdata.get_lang_items()) } </ins> diagnostic_items => { cdata.get_diagnostic_items() } missing_lang_items => { cdata.get_missing_lang_items(tcx) }


) -> impl Iterator<Item = (DefId, DefId)> + '_ { self.get_crate_data(cnum).get_inherent_impls() } <ins> /// Decodes all lang items in the crate (for rustdoc). pub fn lang_items_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ { self.get_crate_data(cnum).get_lang_items().map(|(def_id, _)| def_id) } </ins> } impl CrateStore for CStore {


Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); let all_inherent_impls = Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); <ins> let all_lang_items = Vec::from_iter(self.resolver.cstore().lang_items_untracked(cnum)); </ins> // Querying traits in scope is expensive so we try to prune the impl and traits lists // using privacy, private traits and impls from other crates are never documented in


self.add_traits_in_parent_scope(impl_def_id); } } <ins> for def_id in all_lang_items { self.add_traits_in_parent_scope(def_id); } </ins> self.all_traits.extend(all_traits); self.all_trait_impls.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));


<ins> // no-prefer-dynamic #![feature(lang_items)] #![crate_type = "rlib"] #![no_std] pub struct DerefsToF64(f64); impl core::ops::Deref for DerefsToF64 { type Target = f64; fn deref(&self) -> &Self::Target { &self.0 } } mod inner { #[lang = "f64_runtime"] impl f64 { /// [f64::clone] pub fn method() {} } } #[lang = "eh_personality"] fn foo() {} #[panic_handler] fn bar(_: &core::panic::PanicInfo) -> ! { loop {} } </ins>


<ins> // Reexport of a structure that derefs to a type with lang item impls having doc links in their // comments. The doc link points to an associated item, so we check that traits in scope for that // link are populated. // aux-build:extern-lang-item-impl-dep.rs #![no_std] extern crate extern_lang_item_impl_dep; pub use extern_lang_item_impl_dep::DerefsToF64; </ins>


ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => { pointer_or_reference_metadata(cx, t, pointee_type, unique_type_id) } <del> ty::Adt(def, _) if def.is_box() => { </del> <ins> // Box<T, A> may have a non-ZST allocator A. In that case, we // cannot treat Box<T, A> as just an owned alias of `*mut T`. ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { </ins> pointer_or_reference_metadata(cx, t, t.boxed_ty(), unique_type_id) } ty::FnDef(..) | ty::FnPtr(_) => subroutine_type_metadata(cx, unique_type_id),


<ins> // build-pass // compile-flags: -Cdebuginfo=2 // fixes issue #94725 #![feature(allocator_api)] use std::alloc::{AllocError, Allocator, Layout}; use std::ptr::NonNull; struct ZST; unsafe impl Allocator for &ZST { fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { todo!() } unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { todo!() } } fn main() { let _ = Box::<i32, &ZST>::new_in(43, &ZST); } </ins>


<del> // check-pass </del> <ins> // build-pass </ins> // compile-flags: -Cdebuginfo=2 // fixes issue #94149


<ins> // run-pass // regression test for issue #94923 // min-llvm-version: 15.0.0 // compile-flags: -C opt-level=3 fn f0<T>(mut x: usize) -> usize { for _ in 0..1000 { x *= 123; x %= 99 } x + 321 // function composition is not just longer iteration } fn f1<T>(x: usize) -> usize { f0::<(i8, T)>(f0::<(u8, T)>(x)) } fn f2<T>(x: usize) -> usize { f1::<(i8, T)>(f1::<(u8, T)>(x)) } fn f3<T>(x: usize) -> usize { f2::<(i8, T)>(f2::<(u8, T)>(x)) } fn f4<T>(x: usize) -> usize { f3::<(i8, T)>(f3::<(u8, T)>(x)) } fn f5<T>(x: usize) -> usize { f4::<(i8, T)>(f4::<(u8, T)>(x)) } fn f6<T>(x: usize) -> usize { f5::<(i8, T)>(f5::<(u8, T)>(x)) } fn f7<T>(x: usize) -> usize { f6::<(i8, T)>(f6::<(u8, T)>(x)) } fn f8<T>(x: usize) -> usize { f7::<(i8, T)>(f7::<(u8, T)>(x)) } fn main() { let y = f8::<()>(1); assert_eq!(y, 348); } </ins>


hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id)); <del> let err_ty_str; let mut is_ptr = true; let err = if tcx.features().adt_const_params { match ty.peel_refs().kind() { </del> <ins> if tcx.features().adt_const_params { let err = match ty.peel_refs().kind() { </ins> ty::FnPtr(_) => Some("function pointers"), ty::RawPtr(_) => Some("raw pointers"), _ => None, <ins> }; if let Some(unsupported_type) = err { tcx.sess.span_err( hir_ty.span, &format!( "using {} as const generic parameters is forbidden", unsupported_type ), ); } if traits::search_for_structural_match_violation(param.span, tcx, ty).is_some() { // We use the same error code in both branches, because this is really the same // issue: we just special-case the message for type parameters to make it // clearer. if let ty::Param(_) = ty.peel_refs().kind() { // Const parameters may not have type parameters as their types, // because we cannot be sure that the type parameter derives `PartialEq` // and `Eq` (just implementing them is not enough for `structural_match`). struct_span_err!( tcx.sess, hir_ty.span, E0741, "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be  used as the type of a const parameter", ty, ) .span_label( hir_ty.span, format!("`{}` may not derive both `PartialEq` and `Eq`", ty), ) .note( "it is not currently possible to use a type parameter as the type of a  const parameter", ) .emit(); } else { struct_span_err!( tcx.sess, hir_ty.span, E0741, "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as  the type of a const parameter", ty, ) .span_label( hir_ty.span, format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), ) .emit(); } </ins> } } else { <del> match ty.kind() { </del> <ins> let err_ty_str; let mut is_ptr = true; let err = match ty.kind() { </ins> ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None, ty::FnPtr(_) => Some("function pointers"), ty::RawPtr(_) => Some("raw pointers"),


err_ty_str = format!("`{}`", ty); Some(err_ty_str.as_str()) } <del> } }; if let Some(unsupported_type) = err { if is_ptr { tcx.sess.span_err( hir_ty.span, &format!( "using {} as const generic parameters is forbidden", unsupported_type ), ); } else { let mut err = tcx.sess.struct_span_err( hir_ty.span, &format!( "{} is forbidden as the type of a const generic parameter", unsupported_type ), ); err.note("the only supported types are integers, `bool` and `char`"); if tcx.sess.is_nightly_build() { err.help( </del> <ins> }; if let Some(unsupported_type) = err { if is_ptr { tcx.sess.span_err( hir_ty.span, &format!( "using {} as const generic parameters is forbidden", unsupported_type ), ); } else { let mut err = tcx.sess.struct_span_err( hir_ty.span, &format!( "{} is forbidden as the type of a const generic parameter", unsupported_type ), ); err.note("the only supported types are integers, `bool` and `char`"); if tcx.sess.is_nightly_build() { err.help( </ins> "more complex types are supported with `#![feature(adt_const_params)]`", ); <ins> } err.emit(); </ins> } <del> err.emit(); } }; if traits::search_for_structural_match_violation(param.span, tcx, ty).is_some() { // We use the same error code in both branches, because this is really the same // issue: we just special-case the message for type parameters to make it // clearer. if let ty::Param(_) = ty.peel_refs().kind() { // Const parameters may not have type parameters as their types, // because we cannot be sure that the type parameter derives `PartialEq` // and `Eq` (just implementing them is not enough for `structural_match`). struct_span_err!( tcx.sess, hir_ty.span, E0741, "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be  used as the type of a const parameter", ty, ) .span_label( hir_ty.span, format!("`{}` may not derive both `PartialEq` and `Eq`", ty), ) .note( "it is not currently possible to use a type parameter as the type of a  const parameter", ) .emit(); } else { struct_span_err!( tcx.sess, hir_ty.span, E0741, "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as  the type of a const parameter", ty, ) .span_label( hir_ty.span, format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), ) .emit(); </del> } } }


= note: the only supported types are integers, `bool` and `char` = help: more complex types are supported with `#![feature(adt_const_params)]` <del> error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter --> $DIR/issue-63322-forbid-dyn.rs:9:18 | LL | fn test<const T: &'static dyn A>() { |                  ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq` error: aborting due to 2 previous errors </del> <ins> error: aborting due to previous error </ins> <del> For more information about this error, try `rustc --explain E0741`. </del>


impl A for B {} fn test<const T: &'static dyn A>() { <del> //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used </del> <ins> //[full]~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used </ins> //[min]~^^ ERROR `&'static (dyn A + 'static)` is forbidden unimplemented!() }


= note: the only supported types are integers, `bool` and `char` = help: more complex types are supported with `#![feature(adt_const_params)]` <del> error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants --> $DIR/nested-type.rs:15:5 | LL |     Foo::<17>::value() |     ^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 2 previous errors </del> <ins> error: aborting due to previous error </ins> <del> For more information about this error, try `rustc --explain E0015`. </del>


} Foo::<17>::value() <del> //~^ ERROR cannot call non-const fn </del> <ins> //[full]~^ ERROR cannot call non-const fn </ins> }]>; fn main() {}


use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; use alloc::boxed::Box; <ins> use core::marker::PhantomData; </ins> use core::mem::{align_of, size_of}; use core::ptr::NonNull;


const TAG_OS: usize = 0b10; const TAG_SIMPLE: usize = 0b11; <ins> /// The internal representation. /// /// See the module docs for more, this is just a way to hack in a check that we /// indeed are not unwind-safe. /// /// ```compile_fail,E0277 /// fn is_unwind_safe<T: core::panic::UnwindSafe>() {} /// is_unwind_safe::<std::io::Error>(); /// ``` </ins> #[repr(transparent)] <del> pub(super) struct Repr(NonNull<()>); </del> <ins> pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>); </ins> // All the types `Repr` stores internally are Send + Sync, and so is it. unsafe impl Send for Repr {}


// box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore, // `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the // `new_unchecked` is safe. <del> let res = Self(unsafe { NonNull::new_unchecked(tagged) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");


pub(super) fn new_os(code: i32) -> Self { let utagged = ((code as usize) << 32) | TAG_OS; // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. <del> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(


pub(super) fn new_simple(kind: ErrorKind) -> Self { let utagged = ((kind as usize) << 32) | TAG_SIMPLE; // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. <del> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(


#[inline] pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self { // Safety: References are never null. <del> Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }) </del> <ins> Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData) </ins> } #[inline]


//! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. <del> use std::collections::HashSet; </del> use std::fs; use std::io; use std::path::{Path, PathBuf};


let paths = builder .paths .iter() <del> .map(components_simplified) .filter_map(|path| { if path.get(0) == Some(&"compiler") { path.get(1).map(|p| p.to_owned()) } else { None } </del> <ins> .filter(|path| { let components = components_simplified(path); components.len() >= 2 && components[0] == "compiler" </ins> }) .collect::<Vec<_>>();


cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); <del> let mut compiler_crates = HashSet::new(); if paths.is_empty() { // Find dependencies for top level crates. for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { compiler_crates.extend( builder .in_tree_crates(root_crate, Some(target)) .into_iter() .map(|krate| krate.name), ); } </del> <ins> let root_crates = if paths.is_empty() { vec![ INTERNER.intern_str("rustc_driver"), INTERNER.intern_str("rustc_codegen_llvm"), INTERNER.intern_str("rustc_codegen_ssa"), ] </ins> } else { <del> for root_crate in paths { if !builder.src.join("compiler").join(&root_crate).exists() { builder.info(&format!( "tskipping - compiler/{} (unknown compiler crate)", root_crate )); } else { compiler_crates.extend( builder .in_tree_crates(root_crate, Some(target)) .into_iter() .map(|krate| krate.name), ); } } } </del> <ins> paths.into_iter().map(|p| builder.crate_paths[p]).collect() }; // Find dependencies for top level crates. let compiler_crates = root_crates.iter().flat_map(|krate| { builder.in_tree_crates(krate, Some(target)).into_iter().map(|krate| krate.name) }); </ins> let mut to_open = None; <del> for krate in &compiler_crates { </del> <ins> for krate in compiler_crates { </ins> // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself.


ar: HashMap<TargetSelection, PathBuf>, ranlib: HashMap<TargetSelection, PathBuf>, // Miscellaneous <ins> // allow bidirectional lookups: both name -> path and path -> name </ins> crates: HashMap<Interned<String>, Crate>, <ins> crate_paths: HashMap<PathBuf, Interned<String>>, </ins> is_sudo: bool, ci_env: CiEnv, delayed_failures: RefCell<Vec<String>>,


ar: HashMap::new(), ranlib: HashMap::new(), crates: HashMap::new(), <ins> crate_paths: HashMap::new(), </ins> is_sudo, ci_env: CiEnv::current(), delayed_failures: RefCell::new(Vec::new()),


.filter(|dep| dep.source.is_none()) .map(|dep| INTERNER.intern_string(dep.name)) .collect(); <del> build.crates.insert(name, Crate { name, deps, path }); </del> <ins> let krate = Crate { name, deps, path }; let relative_path = krate.local_path(build); build.crates.insert(name, krate); let existing_path = build.crate_paths.insert(relative_path, name); assert!(existing_path.is_none(), "multiple crates with the same path"); </ins> } } }


use crate::tool::{self, SourceType, Tool}; use crate::toolstate::ToolState; use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t}; <del> use crate::Crate as CargoCrate; </del> use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/tmp/work";


fn make_run(run: RunConfig<'_>) { let builder = run.builder; let compiler = builder.compiler(builder.top_stage, run.build_triple()); <ins> let krate = builder.crate_paths[&run.path]; let test_kind = builder.kind.into(); </ins> <del> for krate in builder.in_tree_crates("rustc-main", Some(run.target)) { if krate.path.ends_with(&run.path) { let test_kind = builder.kind.into(); builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, krate: krate.name, }); } } </del> <ins> builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, krate }); </ins> } fn run(self, builder: &Builder<'_>) {


fn make_run(run: RunConfig<'_>) { let builder = run.builder; let compiler = builder.compiler(builder.top_stage, run.build_triple()); <ins> let test_kind = builder.kind.into(); let krate = builder.crate_paths[&run.path]; </ins> <del> let make = |mode: Mode, krate: &CargoCrate| { let test_kind = builder.kind.into(); builder.ensure(Crate { compiler, target: run.target, mode, test_kind, krate: krate.name, }); }; for krate in builder.in_tree_crates("test", Some(run.target)) { if krate.path.ends_with(&run.path) { make(Mode::Std, krate); } } </del> <ins> builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, test_kind, krate }); </ins> } /// Runs all unit tests plus documentation tests for a given crate defined


if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { abi = Abi::Uninhabited; <del> } else if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { // Without latter check aligned enums with custom discriminant values // Would result in ICE see the issue #92464 for more info </del> <ins> } else if tag.size(dl) == size { // Make sure we only use scalar layout when the enum is entirely its // own tag (i.e. it has no padding nor any non-ZST variant fields). </ins> abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums.


fn main() { let aligned = Aligned::Zero; let fo = aligned as u8; <del> println!("foo {}",fo); </del> <ins> println!("foo {}", fo); assert_eq!(fo, 0); println!("{}", tou8(Aligned::Zero)); assert_eq!(tou8(Aligned::Zero), 0); } #[inline(never)] fn tou8(al: Aligned) -> u8 { // Cast behind a function call so ConstProp does not see it // (so that we can test codegen). al as u8 </ins> }


<ins> // normalize-stderr-test "pref: Align([1-8] bytes)" -> "pref: $$PREF_ALIGN" #![crate_type = "lib"] #![feature(rustc_attrs)] // This cannot use `Scalar` abi since there is padding. #[rustc_layout(debug)] #[repr(align(8))] pub enum Aligned1 { //~ ERROR: layout_of Zero = 0, One = 1, } // This should use `Scalar` abi. #[rustc_layout(debug)] #[repr(align(1))] pub enum Aligned2 { //~ ERROR: layout_of Zero = 0, One = 1, } </ins>


<ins> error: layout_of(Aligned1) = Layout { fields: Arbitrary { offsets: [ Size(0 bytes), ], memory_index: [ 0, ], }, variants: Multiple { tag: Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, tag_encoding: Direct, tag_field: 0, variants: [ Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 0, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), }, Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 1, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), }, ], }, abi: Aggregate { sized: true, }, largest_niche: Some( Niche { offset: Size(0 bytes), value: Int( I8, false, ), valid_range: 0..=1, }, ), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:8:1 | LL | pub enum Aligned1 { | ^^^^^^^^^^^^^^^^^ error: layout_of(Aligned2) = Layout { fields: Arbitrary { offsets: [ Size(0 bytes), ], memory_index: [ 0, ], }, variants: Multiple { tag: Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, tag_encoding: Direct, tag_field: 0, variants: [ Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 0, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), }, Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 1, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), }, ], }, abi: Scalar( Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, ), largest_niche: Some( Niche { offset: Size(0 bytes), value: Int( I8, false, ), valid_range: 0..=1, }, ), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:16:1 | LL | pub enum Aligned2 { | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors </ins>


// so add an empty section. if file.format() == object::BinaryFormat::Coff { file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text); <ins> // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the // default mangler in `object` crate. file.set_mangling(object::write::Mangling::None); </ins> } for (sym, kind) in symbols.iter() {


for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { if info.level.is_below_threshold(export_threshold) || info.used { symbols.push(( <del> symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum), </del> <ins> symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), </ins> info.kind, )); }


use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; <del> use rustc_middle::ty::{SymbolName, TyCtxt}; </del> <ins> use rustc_middle::ty::{self, SymbolName, TyCtxt}; </ins> use rustc_session::config::CrateType; use rustc_target::spec::SanitizerSet;


} } <ins> /// This is the symbol name of the given instance as seen by the linker. /// /// On 32-bit Windows symbols are decorated according to their calling conventions. pub fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, ) -> String { use rustc_target::abi::call::Conv; let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); let target = &tcx.sess.target; if !target.is_like_windows { // Mach-O has a global "_" suffix and `object` crate will handle it. // ELF does not have any symbol decorations. return undecorated; } let x86 = match &target.arch[..] { "x86" => true, "x86_64" => false, // Only x86/64 use symbol decorations. _ => return undecorated, }; let instance = match symbol { ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) if tcx.is_static(def_id) => { None } ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), ExportedSymbol::Generic(def_id, substs) => Some(Instance::new(def_id, substs)), // DropGlue always use the Rust calling convention and thus follow the target's default // symbol decoration scheme. ExportedSymbol::DropGlue(..) => None, // NoDefId always follow the target's default symbol decoration scheme. ExportedSymbol::NoDefId(..) => None, }; let (conv, args) = instance .map(|i| { tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty()))) .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) }) .map(|fnabi| (fnabi.conv, &fnabi.args[..])) .unwrap_or((Conv::Rust, &[])); // Decorate symbols with prefices, suffices and total number of bytes of arguments. // Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170 let (prefix, suffix) = match conv { Conv::X86Fastcall => ("@", "@"), Conv::X86Stdcall => ("_", "@"), Conv::X86VectorCall => ("", "@@"), _ => { if x86 { undecorated.insert(0, '_'); } return undecorated; } }; let args_in_bytes: u64 = args .iter() .map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8)) .sum(); format!("{prefix}{undecorated}{suffix}{args_in_bytes}") } </ins> fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, String> { // Build up a map from DefId to a `NativeLib` structure, where // `NativeLib` internally contains information about


#![feature(nll)] #![feature(associated_type_bounds)] #![feature(strict_provenance)] <ins> #![feature(int_roundings)] </ins> #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)]


<ins> // build-pass // only-x86-windows #![crate_type = "cdylib"] #![feature(abi_vectorcall)] #[no_mangle] extern "stdcall" fn foo(_: bool) {} #[no_mangle] extern "fastcall" fn bar(_: u8) {} #[no_mangle] extern "vectorcall" fn baz(_: u16) {} </ins>


.arg("--target-dir") .arg(&*target_dir.to_string_lossy()) .arg("-Zskip-rustdoc-fingerprint") <ins> .arg("-Zrustdoc-map") .rustdocflag("--extern-html-root-url") .rustdocflag("std_detect=https://docs.rs/std_detect/latest/") .rustdocflag("--extern-html-root-takes-precedence") </ins> .rustdocflag("--resource-suffix") .rustdocflag(&builder.version); for arg in extra_args {


entry.unwrap(); } } <ins> /// Test the fallback for getting the metadata of files like hiberfil.sys that /// Windows holds a special lock on, preventing normal means of querying /// metadata. See #96980. /// /// Note this fails in CI because `hiberfil.sys` does not actually exist there. /// Therefore it's marked as ignored. #[test] #[ignore] #[cfg(windows)] fn hiberfil_sys() { let hiberfil = Path::new(r"C:hiberfil.sys"); assert_eq!(true, hiberfil.try_exists().unwrap()); fs::symlink_metadata(hiberfil).unwrap(); fs::metadata(hiberfil).unwrap(); assert_eq!(true, hiberfil.exists()); } </ins>