diff options
435 files changed, 7508 insertions, 3656 deletions
diff --git a/.github/ISSUE_TEMPLATE/tracking_issue_future.md b/.github/ISSUE_TEMPLATE/tracking_issue_future.md index f04a458d8a5..d3a7c4cc9ee 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue_future.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue_future.md @@ -14,7 +14,7 @@ it would be `T-libs-api`. Also check for any `A-` labels to add. --> -This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibility warning and other related errors. The goal of this page is describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our [breaking change policy guidelines][guidelines]. +This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibility warning and other related errors. The goal of this page is to describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our [breaking change policy guidelines][guidelines]. [guidelines]: https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html @@ -44,7 +44,7 @@ This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibilit - [ ] Implement the lint - [ ] Raise lint level to deny -- [ ] Make lint report in dependencies +- [ ] Change the lint to report in dependencies - [ ] Switch to a hard error ### Implementation history diff --git a/Cargo.lock b/Cargo.lock index 1cff2f22f4f..6d823c5b5a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4474,6 +4474,7 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", + "rustc_index", "rustc_macros", "rustc_metadata", "rustc_middle", @@ -4552,9 +4553,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "scoped-tls", - "serde", - "tracing", ] [[package]] @@ -4622,6 +4620,7 @@ dependencies = [ "rand 0.9.1", "rand_xorshift", "scoped-tls", + "smallvec", ] [[package]] @@ -5107,7 +5106,16 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "stable_mir" version = "0.1.0-preview" dependencies = [ + "rustc_abi", + "rustc_hir", + "rustc_middle", + "rustc_session", "rustc_smir", + "rustc_span", + "rustc_target", + "scoped-tls", + "serde", + "tracing", ] [[package]] diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a438545c76f..de4b5a46c81 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -221,6 +221,20 @@ impl ReprOptions { /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. pub const MAX_SIMD_LANES: u64 = 1 << 0xF; +/// How pointers are represented in a given address space +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct PointerSpec { + /// The size of the bitwise representation of the pointer. + pointer_size: Size, + /// The alignment of pointers for this address space + pointer_align: AbiAlign, + /// The size of the value a pointer can be offset by in this address space. + pointer_offset: Size, + /// Pointers into this address space contain extra metadata + /// FIXME(workingjubilee): Consider adequately reflecting this in the compiler? + _is_fat: bool, +} + /// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout) /// for a target, which contains everything needed to compute layouts. #[derive(Debug, PartialEq, Eq)] @@ -236,13 +250,22 @@ pub struct TargetDataLayout { pub f32_align: AbiAlign, pub f64_align: AbiAlign, pub f128_align: AbiAlign, - pub pointer_size: Size, - pub pointer_align: AbiAlign, pub aggregate_align: AbiAlign, /// Alignments for vector types. pub vector_align: Vec<(Size, AbiAlign)>, + pub default_address_space: AddressSpace, + pub default_address_space_pointer_spec: PointerSpec, + + /// Address space information of all known address spaces. + /// + /// # Note + /// + /// This vector does not contain the [`PointerSpec`] relative to the default address space, + /// which instead lives in [`Self::default_address_space_pointer_spec`]. + address_space_info: Vec<(AddressSpace, PointerSpec)>, + pub instruction_address_space: AddressSpace, /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32) @@ -267,14 +290,20 @@ impl Default for TargetDataLayout { f32_align: AbiAlign::new(align(32)), f64_align: AbiAlign::new(align(64)), f128_align: AbiAlign::new(align(128)), - pointer_size: Size::from_bits(64), - pointer_align: AbiAlign::new(align(64)), aggregate_align: AbiAlign { abi: align(8) }, vector_align: vec![ (Size::from_bits(64), AbiAlign::new(align(64))), (Size::from_bits(128), AbiAlign::new(align(128))), ], - instruction_address_space: AddressSpace::DATA, + default_address_space: AddressSpace::ZERO, + default_address_space_pointer_spec: PointerSpec { + pointer_size: Size::from_bits(64), + pointer_align: AbiAlign::new(align(64)), + pointer_offset: Size::from_bits(64), + _is_fat: false, + }, + address_space_info: vec![], + instruction_address_space: AddressSpace::ZERO, c_enum_min_size: Integer::I32, } } @@ -288,6 +317,7 @@ pub enum TargetDataLayoutErrors<'a> { InconsistentTargetArchitecture { dl: &'a str, target: &'a str }, InconsistentTargetPointerWidth { pointer_size: u64, target: u32 }, InvalidBitsSize { err: String }, + UnknownPointerSpecification { err: String }, } impl TargetDataLayout { @@ -298,6 +328,7 @@ impl TargetDataLayout { /// determined from llvm string. pub fn parse_from_llvm_datalayout_string<'a>( input: &'a str, + default_address_space: AddressSpace, ) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> { // Parse an address space index from a string. let parse_address_space = |s: &'a str, cause: &'a str| { @@ -321,19 +352,27 @@ impl TargetDataLayout { |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits); // Parse an alignment string. - let parse_align = |s: &[&'a str], cause: &'a str| { - if s.is_empty() { - return Err(TargetDataLayoutErrors::MissingAlignment { cause }); - } + let parse_align_str = |s: &'a str, cause: &'a str| { let align_from_bits = |bits| { Align::from_bits(bits) .map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err }) }; - let abi = parse_bits(s[0], "alignment", cause)?; + let abi = parse_bits(s, "alignment", cause)?; Ok(AbiAlign::new(align_from_bits(abi)?)) }; + // Parse an alignment sequence, possibly in the form `<align>[:<preferred_alignment>]`, + // ignoring the secondary alignment specifications. + let parse_align_seq = |s: &[&'a str], cause: &'a str| { + if s.is_empty() { + return Err(TargetDataLayoutErrors::MissingAlignment { cause }); + } + parse_align_str(s[0], cause) + }; + let mut dl = TargetDataLayout::default(); + dl.default_address_space = default_address_space; + let mut i128_align_src = 64; for spec in input.split('-') { let spec_parts = spec.split(':').collect::<Vec<_>>(); @@ -344,24 +383,107 @@ impl TargetDataLayout { [p] if p.starts_with('P') => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - ["a", a @ ..] => dl.aggregate_align = parse_align(a, "a")?, - ["f16", a @ ..] => dl.f16_align = parse_align(a, "f16")?, - ["f32", a @ ..] => dl.f32_align = parse_align(a, "f32")?, - ["f64", a @ ..] => dl.f64_align = parse_align(a, "f64")?, - ["f128", a @ ..] => dl.f128_align = parse_align(a, "f128")?, - // FIXME(erikdesjardins): we should be parsing nonzero address spaces - // this will require replacing TargetDataLayout::{pointer_size,pointer_align} - // with e.g. `fn pointer_size_in(AddressSpace)` - [p @ "p", s, a @ ..] | [p @ "p0", s, a @ ..] => { - dl.pointer_size = parse_size(s, p)?; - dl.pointer_align = parse_align(a, p)?; + ["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a")?, + ["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16")?, + ["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32")?, + ["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64")?, + ["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?, + [p, s, a @ ..] if p.starts_with("p") => { + let mut p = p.strip_prefix('p').unwrap(); + let mut _is_fat = false; + + // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that + // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`. + + if p.starts_with('f') { + p = p.strip_prefix('f').unwrap(); + _is_fat = true; + } + + // However, we currently don't take into account further specifications: + // an error is emitted instead. + if p.starts_with(char::is_alphabetic) { + return Err(TargetDataLayoutErrors::UnknownPointerSpecification { + err: p.to_string(), + }); + } + + let addr_space = if !p.is_empty() { + parse_address_space(p, "p-")? + } else { + AddressSpace::ZERO + }; + + let pointer_size = parse_size(s, "p-")?; + let pointer_align = parse_align_seq(a, "p-")?; + let info = PointerSpec { + pointer_offset: pointer_size, + pointer_size, + pointer_align, + _is_fat, + }; + if addr_space == default_address_space { + dl.default_address_space_pointer_spec = info; + } else { + match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) { + Some(e) => e.1 = info, + None => { + dl.address_space_info.push((addr_space, info)); + } + } + } + } + [p, s, a, _pr, i] if p.starts_with("p") => { + let mut p = p.strip_prefix('p').unwrap(); + let mut _is_fat = false; + + // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that + // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`. + + if p.starts_with('f') { + p = p.strip_prefix('f').unwrap(); + _is_fat = true; + } + + // However, we currently don't take into account further specifications: + // an error is emitted instead. + if p.starts_with(char::is_alphabetic) { + return Err(TargetDataLayoutErrors::UnknownPointerSpecification { + err: p.to_string(), + }); + } + + let addr_space = if !p.is_empty() { + parse_address_space(p, "p")? + } else { + AddressSpace::ZERO + }; + + let info = PointerSpec { + pointer_size: parse_size(s, "p-")?, + pointer_align: parse_align_str(a, "p-")?, + pointer_offset: parse_size(i, "p-")?, + _is_fat, + }; + + if addr_space == default_address_space { + dl.default_address_space_pointer_spec = info; + } else { + match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) { + Some(e) => e.1 = info, + None => { + dl.address_space_info.push((addr_space, info)); + } + } + } } + [s, a @ ..] if s.starts_with('i') => { let Ok(bits) = s[1..].parse::<u64>() else { parse_size(&s[1..], "i")?; // For the user error. continue; }; - let a = parse_align(a, s)?; + let a = parse_align_seq(a, s)?; match bits { 1 => dl.i1_align = a, 8 => dl.i8_align = a, @@ -379,7 +501,7 @@ impl TargetDataLayout { } [s, a @ ..] if s.starts_with('v') => { let v_size = parse_size(&s[1..], "v")?; - let a = parse_align(a, s)?; + let a = parse_align_seq(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { v.1 = a; continue; @@ -390,10 +512,27 @@ impl TargetDataLayout { _ => {} // Ignore everything else. } } + + // Inherit, if not given, address space information for specific LLVM elements from the + // default data address space. + if (dl.instruction_address_space != dl.default_address_space) + && dl + .address_space_info + .iter() + .find(|(a, _)| *a == dl.instruction_address_space) + .is_none() + { + dl.address_space_info.push(( + dl.instruction_address_space, + dl.default_address_space_pointer_spec.clone(), + )); + } + Ok(dl) } - /// Returns **exclusive** upper bound on object size in bytes. + /// Returns **exclusive** upper bound on object size in bytes, in the default data address + /// space. /// /// The theoretical maximum object size is defined as the maximum positive `isize` value. /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly @@ -404,7 +543,26 @@ impl TargetDataLayout { /// so we adopt such a more-constrained size bound due to its technical limitations. #[inline] pub fn obj_size_bound(&self) -> u64 { - match self.pointer_size.bits() { + match self.pointer_size().bits() { + 16 => 1 << 15, + 32 => 1 << 31, + 64 => 1 << 61, + bits => panic!("obj_size_bound: unknown pointer bit size {bits}"), + } + } + + /// Returns **exclusive** upper bound on object size in bytes. + /// + /// The theoretical maximum object size is defined as the maximum positive `isize` value. + /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly + /// index every address within an object along with one byte past the end, along with allowing + /// `isize` to store the difference between any two pointers into an object. + /// + /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes, + /// so we adopt such a more-constrained size bound due to its technical limitations. + #[inline] + pub fn obj_size_bound_in(&self, address_space: AddressSpace) -> u64 { + match self.pointer_size_in(address_space).bits() { 16 => 1 << 15, 32 => 1 << 31, 64 => 1 << 61, @@ -415,7 +573,18 @@ impl TargetDataLayout { #[inline] pub fn ptr_sized_integer(&self) -> Integer { use Integer::*; - match self.pointer_size.bits() { + match self.pointer_offset().bits() { + 16 => I16, + 32 => I32, + 64 => I64, + bits => panic!("ptr_sized_integer: unknown pointer bit size {bits}"), + } + } + + #[inline] + pub fn ptr_sized_integer_in(&self, address_space: AddressSpace) -> Integer { + use Integer::*; + match self.pointer_offset_in(address_space).bits() { 16 => I16, 32 => I32, 64 => I64, @@ -439,6 +608,66 @@ impl TargetDataLayout { Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(), )) } + + /// Get the pointer size in the default data address space. + #[inline] + pub fn pointer_size(&self) -> Size { + self.default_address_space_pointer_spec.pointer_size + } + + /// Get the pointer size in a specific address space. + #[inline] + pub fn pointer_size_in(&self, c: AddressSpace) -> Size { + if c == self.default_address_space { + return self.default_address_space_pointer_spec.pointer_size; + } + + if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) { + e.1.pointer_size + } else { + panic!("Use of unknown address space {c:?}"); + } + } + + /// Get the pointer index in the default data address space. + #[inline] + pub fn pointer_offset(&self) -> Size { + self.default_address_space_pointer_spec.pointer_offset + } + + /// Get the pointer index in a specific address space. + #[inline] + pub fn pointer_offset_in(&self, c: AddressSpace) -> Size { + if c == self.default_address_space { + return self.default_address_space_pointer_spec.pointer_offset; + } + + if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) { + e.1.pointer_offset + } else { + panic!("Use of unknown address space {c:?}"); + } + } + + /// Get the pointer alignment in the default data address space. + #[inline] + pub fn pointer_align(&self) -> AbiAlign { + self.default_address_space_pointer_spec.pointer_align + } + + /// Get the pointer alignment in a specific address space. + #[inline] + pub fn pointer_align_in(&self, c: AddressSpace) -> AbiAlign { + if c == self.default_address_space { + return self.default_address_space_pointer_spec.pointer_align; + } + + if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) { + e.1.pointer_align + } else { + panic!("Use of unknown address space {c:?}"); + } + } } pub trait HasDataLayout { @@ -1100,10 +1329,7 @@ impl Primitive { match self { Int(i, _) => i.size(), Float(f) => f.size(), - // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in - // different address spaces can have different sizes - // (but TargetDataLayout doesn't currently parse that part of the DL string) - Pointer(_) => dl.pointer_size, + Pointer(a) => dl.pointer_size_in(a), } } @@ -1114,10 +1340,7 @@ impl Primitive { match self { Int(i, _) => i.align(dl), Float(f) => f.align(dl), - // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in - // different address spaces can have different alignments - // (but TargetDataLayout doesn't currently parse that part of the DL string) - Pointer(_) => dl.pointer_align, + Pointer(a) => dl.pointer_align_in(a), } } } @@ -1421,8 +1644,8 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> { pub struct AddressSpace(pub u32); impl AddressSpace { - /// The default address space, corresponding to data space. - pub const DATA: Self = AddressSpace(0); + /// LLVM's `0` address space. + pub const ZERO: Self = AddressSpace(0); } /// The way we represent values to the backend diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 491a9bbda79..3c576316f62 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2422,7 +2422,7 @@ impl Ty { } #[derive(Clone, Encodable, Decodable, Debug)] -pub struct BareFnTy { +pub struct FnPtrTy { pub safety: Safety, pub ext: Extern, pub generic_params: ThinVec<GenericParam>, @@ -2455,8 +2455,8 @@ pub enum TyKind { /// /// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`. PinnedRef(Option<Lifetime>, MutTy), - /// A bare function (e.g., `fn(usize) -> bool`). - BareFn(P<BareFnTy>), + /// A function pointer type (e.g., `fn(usize) -> bool`). + FnPtr(P<FnPtrTy>), /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`). UnsafeBinder(P<UnsafeBinderTy>), /// The never type (`!`). diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 989ebe14bf8..f7daec4b064 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -265,7 +265,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { ty = &binder.inner_ty; } - ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output { + ast::TyKind::FnPtr(fn_ty) => match &fn_ty.decl.output { ast::FnRetTy::Default(_) => break None, ast::FnRetTy::Ty(ret) => ty = ret, }, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f8ecff69a76..37fcc0d2167 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1059,8 +1059,8 @@ macro_rules! common_visitor_and_walkers { TyKind::Tup(tuple_element_types) => { walk_list!(vis, visit_ty, tuple_element_types); } - TyKind::BareFn(function_declaration) => { - let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = + TyKind::FnPtr(function_declaration) => { + let FnPtrTy { safety, ext: _, generic_params, decl, decl_span } = &$($mut)? **function_declaration; try_visit!(visit_safety(vis, safety)); try_visit!(visit_generic_params(vis, generic_params)); diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 943cde90dd2..5b1dcab87b9 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -55,7 +55,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Get the maximum value of int_ty. It is platform-dependent due to the byte size of isize fn int_ty_max(&self, int_ty: IntTy) -> u128 { match int_ty { - IntTy::Isize => self.tcx.data_layout.pointer_size.signed_int_max() as u128, + IntTy::Isize => self.tcx.data_layout.pointer_size().signed_int_max() as u128, IntTy::I8 => i8::MAX as u128, IntTy::I16 => i16::MAX as u128, IntTy::I32 => i32::MAX as u128, @@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Get the maximum value of uint_ty. It is platform-dependent due to the byte size of usize fn uint_ty_max(&self, uint_ty: UintTy) -> u128 { match uint_ty { - UintTy::Usize => self.tcx.data_layout.pointer_size.unsigned_int_max(), + UintTy::Usize => self.tcx.data_layout.pointer_size().unsigned_int_max(), UintTy::U8 => u8::MAX as u128, UintTy::U16 => u16::MAX as u128, UintTy::U32 => u32::MAX as u128, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0706bdb119f..348fe2ee40a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1269,9 +1269,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args)); hir::TyKind::Path(path) } - TyKind::BareFn(f) => { + TyKind::FnPtr(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); - hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { + hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { generic_params, safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index d58c140c696..c5780c957c9 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -48,9 +48,6 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg -ast_passes_bare_fn_invalid_safety = function pointers cannot be declared with `safe` safety qualifier - .suggestion = remove safe from this item - ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body .invalid = the invalid body @@ -135,6 +132,9 @@ ast_passes_fn_param_forbidden_self = ast_passes_fn_param_too_many = function can not have more than {$max_num_args} arguments +ast_passes_fn_ptr_invalid_safety = function pointers cannot be declared with `safe` safety qualifier + .suggestion = remove safe from this item + ast_passes_fn_without_body = free function without a body .suggestion = provide a definition for the function diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 53e2a1c695a..38889d28151 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -499,9 +499,9 @@ impl<'a> AstValidator<'a> { } } - fn check_bare_fn_safety(&self, span: Span, safety: Safety) { + fn check_fn_ptr_safety(&self, span: Span, safety: Safety) { if matches!(safety, Safety::Safe(_)) { - self.dcx().emit_err(errors::InvalidSafetyOnBareFn { span }); + self.dcx().emit_err(errors::InvalidSafetyOnFnPtr { span }); } } @@ -785,8 +785,8 @@ impl<'a> AstValidator<'a> { fn visit_ty_common(&mut self, ty: &'a Ty) { match &ty.kind { - TyKind::BareFn(bfty) => { - self.check_bare_fn_safety(bfty.decl_span, bfty.safety); + TyKind::FnPtr(bfty) => { + self.check_fn_ptr_safety(bfty.decl_span, bfty.safety); self.check_fn_decl(&bfty.decl, SelfSemantic::No); Self::check_decl_no_pat(&bfty.decl, |span, _, _| { self.dcx().emit_err(errors::PatternFnPointer { span }); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index d387a4a310e..3b2730d4ff9 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -225,8 +225,8 @@ pub(crate) struct InvalidSafetyOnItem { } #[derive(Diagnostic)] -#[diag(ast_passes_bare_fn_invalid_safety)] -pub(crate) struct InvalidSafetyOnBareFn { +#[diag(ast_passes_fn_ptr_invalid_safety)] +pub(crate) struct InvalidSafetyOnFnPtr { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 5d8ee07178d..8114733f406 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -286,9 +286,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { match &ty.kind { - ast::TyKind::BareFn(bare_fn_ty) => { + ast::TyKind::FnPtr(fn_ptr_ty) => { // Function pointers cannot be `const` - self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params); + self.check_late_bound_lifetime_defs(&fn_ptr_ty.generic_params); } ast::TyKind::Never => { gate!(&self, never_type, ty.span, "the `!` type is experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 9802ac90c9a..aff98c63bcb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1285,7 +1285,7 @@ impl<'a> State<'a> { self.print_type(typ); self.pclose(); } - ast::TyKind::BareFn(f) => { + ast::TyKind::FnPtr(f) => { self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params); } ast::TyKind::UnsafeBinder(f) => { diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index ba62be676d4..2cbb7270785 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -149,7 +149,7 @@ pub enum UsedBy { /// ## Attribute Processing /// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams /// because different attributes have different internal structures. This enum represents the final, -/// fully parsed form of these attributes, where each variant contains contains all the information and +/// fully parsed form of these attributes, where each variant contains all the information and /// structure relevant for the specific attribute. /// /// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single @@ -298,6 +298,9 @@ pub enum AttributeKind { /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint). PassByValue(Span), + /// Represents `#[path]` + Path(Symbol, Span), + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). PubTransparent(Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index b109ebbf47b..a6ae49d2808 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -40,6 +40,7 @@ impl AttributeKind { NonExhaustive(..) => Yes, Optimize(..) => No, PassByValue(..) => Yes, + Path(..) => No, PubTransparent(..) => Yes, Repr { .. } => No, RustcLayoutScalarValidRangeEnd(..) => Yes, diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 55fbb825466..ba7572434df 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -37,6 +37,7 @@ pub(crate) mod loop_match; pub(crate) mod must_use; pub(crate) mod no_implicit_prelude; pub(crate) mod non_exhaustive; +pub(crate) mod path; pub(crate) mod repr; pub(crate) mod rustc_internal; pub(crate) mod semantics; diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs new file mode 100644 index 00000000000..0dfbc9a9aa8 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -0,0 +1,29 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct PathParser; + +impl<S: Stage> SingleAttributeParser<S> for PathParser { + const PATH: &[Symbol] = &[sym::path]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(path) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::Path(path, cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index bcd7b024a9e..939f4a6fde7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,6 +28,7 @@ use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; +use crate::attributes::path::PathParser as PathAttributeParser; use crate::attributes::repr::{AlignParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart, @@ -133,6 +134,7 @@ attribute_parsers!( Single<LinkSectionParser>, Single<MustUseParser>, Single<OptimizeParser>, + Single<PathAttributeParser>, Single<RustcForceInlineParser>, Single<RustcLayoutScalarValidRangeEnd>, Single<RustcLayoutScalarValidRangeStart>, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8135f3744f8..8c3093acea4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -414,12 +414,12 @@ fn find_type_parameters( impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &'a ast::Ty) { let stack_len = self.bound_generic_params_stack.len(); - if let ast::TyKind::BareFn(bare_fn) = &ty.kind - && !bare_fn.generic_params.is_empty() + if let ast::TyKind::FnPtr(fn_ptr) = &ty.kind + && !fn_ptr.generic_params.is_empty() { // Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so // that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622 - self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned()); + self.bound_generic_params_stack.extend(fn_ptr.generic_params.iter().cloned()); } if let ast::TyKind::Path(_, path) = &ty.kind diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 8965e4a944d..7d0731c77bd 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -786,7 +786,7 @@ pub(crate) fn codegen_drop<'tcx>( pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam { let param = AbiParam::new(ty); - if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size.bits() { + if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() { match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) { ("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) { (types::I8 | types::I16, true) => param.sext(), diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index cd0afee0cfb..2031842062d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -127,7 +127,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { if on_stack { // Abi requires aligning struct size to pointer size - let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); + let size = self.layout.size.align_to(tcx.data_layout.pointer_align().abi); let size = u32::try_from(size.bytes()).unwrap(); smallvec![apply_attrs_to_abi_param( AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 2f11b2d2dcc..2fbe5c02802 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -15,7 +15,7 @@ use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type { - match tcx.data_layout.pointer_size.bits() { + match tcx.data_layout.pointer_size().bits() { 16 => types::I16, 32 => types::I32, 64 => types::I64, diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ee43eb736e6..ed06423b260 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -443,7 +443,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; - let ptr_size = tcx.data_layout.pointer_size; + let ptr_size = tcx.data_layout.pointer_size(); let bytes = &alloc.inspect_with_uninit_and_ptr_outside_interpreter( offset..offset + ptr_size.bytes() as usize, ); diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index dd582834fac..32713eb56c6 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -162,7 +162,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { } fn const_usize(&self, i: u64) -> RValue<'gcc> { - let bit_size = self.data_layout().pointer_size.bits(); + let bit_size = self.data_layout().pointer_size().bits(); if bit_size < 64 { // make sure it doesn't overflow assert!(i < (1 << bit_size)); diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index b43f9b24c6a..c04c75e1b11 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -294,7 +294,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( let alloc = alloc.inner(); let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let dl = cx.data_layout(); - let pointer_size = dl.pointer_size.bytes() as usize; + let pointer_size = dl.pointer_size().bytes() as usize; let mut next_offset = 0; for &(offset, prov) in alloc.provenance().ptrs().iter() { @@ -331,7 +331,7 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( ), abi::Scalar::Initialized { value: Primitive::Pointer(address_space), - valid_range: WrappingRange::full(dl.pointer_size), + valid_range: WrappingRange::full(dl.pointer_size()), }, cx.type_i8p_ext(address_space), )); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 497605978fe..0753ac1aeb8 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // so we re-use that same threshold here. - layout.size() <= self.data_layout().pointer_size * 2 + layout.size() <= self.data_layout().pointer_size() * 2 } }; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 2e508813fc3..350915a277e 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -1184,7 +1184,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let lhs = args[0].immediate(); let rhs = args[1].immediate(); let is_add = name == sym::simd_saturating_add; - let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; + let ptr_bits = bx.tcx().data_layout.pointer_size().bits() as _; let (signed, elem_width, elem_ty) = match *in_elem.kind() { ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), ty::Uint(i) => { diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 1a6eec0ed0b..d8fae1ca47d 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -19,7 +19,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![feature(rustc_private)] -#![allow(broken_intra_doc_links)] #![recursion_limit = "256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index adb53e0b66c..1ea5a062254 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -370,22 +370,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( }; to_add.extend(inline_attr(cx, inline)); - // The `uwtable` attribute according to LLVM is: - // - // This attribute indicates that the ABI being targeted requires that an - // unwind table entry be produced for this function even if we can show - // that no exceptions passes by it. This is normally the case for the - // ELF x86-64 abi, but it can be disabled for some compilation units. - // - // Typically when we're compiling with `-C panic=abort` (which implies this - // `no_landing_pads` check) we don't need `uwtable` because we can't - // generate any exceptions! On Windows, however, exceptions include other - // events such as illegal instructions, segfaults, etc. This means that on - // Windows we end up still needing the `uwtable` attribute even if the `-C - // panic=abort` flag is passed. - // - // You can also find more info on why Windows always requires uwtables here: - // https://bugzilla.mozilla.org/show_bug.cgi?id=1302078 if cx.sess().must_emit_unwind_tables() { to_add.push(uwtable_attr(cx.llcx, cx.sess().opts.unstable_opts.use_sync_unwind)); } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 7cfab25bc50..92f38565eef 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -175,7 +175,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { } fn const_usize(&self, i: u64) -> &'ll Value { - let bit_size = self.data_layout().pointer_size.bits(); + let bit_size = self.data_layout().pointer_size().bits(); if bit_size < 64 { // make sure it doesn't overflow assert!(i < (1 << bit_size)); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a4492d76c3c..28f5282c6b0 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -43,7 +43,8 @@ pub(crate) fn const_alloc_to_llvm<'ll>( } let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let dl = cx.data_layout(); - let pointer_size = dl.pointer_size.bytes() as usize; + let pointer_size = dl.pointer_size(); + let pointer_size_bytes = pointer_size.bytes() as usize; // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range` // must be within the bounds of `alloc` and not contain or overlap a pointer provenance. @@ -100,7 +101,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>( // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), // and we properly interpret the provenance as a relocation pointer offset. - alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), + alloc.inspect_with_uninit_and_ptr_outside_interpreter( + offset..(offset + pointer_size_bytes), + ), ) .expect("const_alloc_to_llvm: could not read relocation pointer") as u64; @@ -111,11 +114,11 @@ pub(crate) fn const_alloc_to_llvm<'ll>( InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx), Scalar::Initialized { value: Primitive::Pointer(address_space), - valid_range: WrappingRange::full(dl.pointer_size), + valid_range: WrappingRange::full(pointer_size), }, cx.type_ptr_ext(address_space), )); - next_offset = offset + pointer_size; + next_offset = offset + pointer_size_bytes; } if alloc.len() >= next_offset { let range = next_offset..alloc.len(); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0324dff6ff2..90582e23b04 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { GenericCx( FullCx { tcx, - scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size), + scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()), use_dll_storage_attrs, tls_model, codegen_unit, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 7f3e486ca31..9b4736e50e6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -159,13 +159,15 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( return_if_di_node_created_in_meantime!(cx, unique_type_id); let data_layout = &cx.tcx.data_layout; + let pointer_size = data_layout.pointer_size(); + let pointer_align = data_layout.pointer_align(); let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true); match wide_pointer_kind(cx, pointee_type) { None => { // This is a thin pointer. Create a regular pointer type and give it the correct name. assert_eq!( - (data_layout.pointer_size, data_layout.pointer_align.abi), + (pointer_size, pointer_align.abi), cx.size_and_align_of(ptr_type), "ptr_type={ptr_type}, pointee_type={pointee_type}", ); @@ -174,8 +176,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( llvm::LLVMRustDIBuilderCreatePointerType( DIB(cx), pointee_type_di_node, - data_layout.pointer_size.bits(), - data_layout.pointer_align.abi.bits() as u32, + pointer_size.bits(), + pointer_align.abi.bits() as u32, 0, // Ignore DWARF address space. ptr_type_debuginfo_name.as_c_char_ptr(), ptr_type_debuginfo_name.len(), @@ -319,7 +321,9 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); let (size, align) = match fn_ty.kind() { ty::FnDef(..) => (Size::ZERO, Align::ONE), - ty::FnPtr(..) => (cx.tcx.data_layout.pointer_size, cx.tcx.data_layout.pointer_align.abi), + ty::FnPtr(..) => { + (cx.tcx.data_layout.pointer_size(), cx.tcx.data_layout.pointer_align().abi) + } _ => unreachable!(), }; let di_node = unsafe { @@ -504,7 +508,7 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D create_basic_type( cx, "<recur_type>", - cx.tcx.data_layout.pointer_size, + cx.tcx.data_layout.pointer_size(), dwarf_const::DW_ATE_unsigned, ) }) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 35922c100cd..fcc0d378f06 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -458,7 +458,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // so we re-use that same threshold here. - layout.size() <= self.data_layout().pointer_size * 2 + layout.size() <= self.data_layout().pointer_size() * 2 } }; @@ -758,8 +758,8 @@ fn codegen_msvc_try<'ll, 'tcx>( // } // // More information can be found in libstd's seh.rs implementation. - let ptr_size = bx.tcx().data_layout.pointer_size; - let ptr_align = bx.tcx().data_layout.pointer_align.abi; + let ptr_size = bx.tcx().data_layout.pointer_size(); + let ptr_align = bx.tcx().data_layout.pointer_align().abi; let slot = bx.alloca(ptr_size, ptr_align); let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None); @@ -1031,8 +1031,8 @@ fn codegen_emcc_try<'ll, 'tcx>( // We need to pass two values to catch_func (ptr and is_rust_panic), so // create an alloca and pass a pointer to that. - let ptr_size = bx.tcx().data_layout.pointer_size; - let ptr_align = bx.tcx().data_layout.pointer_align.abi; + let ptr_size = bx.tcx().data_layout.pointer_size(); + let ptr_align = bx.tcx().data_layout.pointer_align().abi; let i8_align = bx.tcx().data_layout.i8_align.abi; // Required in order for there to be no padding between the fields. assert!(i8_align <= ptr_align); @@ -1158,9 +1158,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( macro_rules! require_int_or_uint_ty { ($ty: expr, $diag: expr) => { match $ty { - ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), + ty::Int(i) => { + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits()) + } ty::Uint(i) => { - i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits()) } _ => { return_error!($diag); @@ -2014,10 +2016,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } else { let bitwidth = match in_elem.kind() { ty::Int(i) => { - i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits()) } ty::Uint(i) => { - i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size().bits()) } _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index cdfffbe47bf..63ca51b006d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -113,7 +113,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend { ) -> ModuleLlvm { let module_llvm = ModuleLlvm::new_metadata(tcx, module_name); let cx = - SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size); + SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size()); unsafe { allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index 7b00b2da6ba..c696b8d8ff2 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -1,4 +1,3 @@ -#![allow(non_camel_case_types)] #![expect(dead_code)] use libc::{c_char, c_uint}; diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 453eca2bbe1..ee472e75ed4 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -208,7 +208,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> { } fn type_ptr(&self) -> &'ll Type { - self.type_ptr_ext(AddressSpace::DATA) + self.type_ptr_ext(AddressSpace::ZERO) } fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type { @@ -258,7 +258,7 @@ impl Type { } pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type { - unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) } + unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::ZERO.0) } } } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 486dc894a4e..ce079f3cb0a 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -45,7 +45,8 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>( let va_list_ty = bx.type_ptr(); let va_list_addr = list.immediate(); - let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi); + let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi; + let ptr = bx.load(va_list_ty, va_list_addr, ptr_align_abi); let (addr, addr_align) = if allow_higher_align && align > slot_size { (round_pointer_up_to_alignment(bx, ptr, align, bx.type_ptr()), align) @@ -56,7 +57,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>( let aligned_size = size.align_to(slot_size).bytes() as i32; let full_direct_size = bx.cx().const_i32(aligned_size); let next = bx.inbounds_ptradd(addr, full_direct_size); - bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi); + bx.store(next, va_list_addr, ptr_align_abi); if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big @@ -108,8 +109,8 @@ fn emit_ptr_va_arg<'ll, 'tcx>( let (llty, size, align) = if indirect { ( bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx), - bx.cx.data_layout().pointer_size, - bx.cx.data_layout().pointer_align, + bx.cx.data_layout().pointer_size(), + bx.cx.data_layout().pointer_align(), ) } else { (layout.llvm_type(bx.cx), layout.size, layout.align) @@ -204,7 +205,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( bx.switch_to_block(in_reg); let top_type = bx.type_ptr(); - let top = bx.load(top_type, reg_top, dl.pointer_align.abi); + let top = bx.load(top_type, reg_top, dl.pointer_align().abi); // reg_value = *(@top + reg_off_v); let mut reg_addr = bx.ptradd(top, reg_off_v); @@ -297,6 +298,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( let max_regs = 8u8; let use_regs = bx.icmp(IntPredicate::IntULT, num_regs, bx.const_u8(max_regs)); + let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi; let in_reg = bx.append_sibling_block("va_arg.in_reg"); let in_mem = bx.append_sibling_block("va_arg.in_mem"); @@ -308,7 +310,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( bx.switch_to_block(in_reg); let reg_safe_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2 + 4)); - let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, dl.pointer_align.abi); + let mut reg_addr = bx.load(bx.type_ptr(), reg_safe_area_ptr, ptr_align_abi); // Floating-point registers start after the general-purpose registers. if !is_int && !is_soft_float_abi { @@ -342,11 +344,11 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( let size = if !is_indirect { layout.layout.size.align_to(overflow_area_align) } else { - dl.pointer_size + dl.pointer_size() }; let overflow_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(1 + 1 + 2)); - let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, dl.pointer_align.abi); + let mut overflow_area = bx.load(bx.type_ptr(), overflow_area_ptr, ptr_align_abi); // Round up address of argument to alignment if layout.layout.align.abi > overflow_area_align { @@ -362,7 +364,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( // Increase the overflow area. overflow_area = bx.inbounds_ptradd(overflow_area, bx.const_usize(size.bytes())); - bx.store(overflow_area, overflow_area_ptr, dl.pointer_align.abi); + bx.store(overflow_area, overflow_area_ptr, ptr_align_abi); bx.br(end); @@ -373,11 +375,8 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( bx.switch_to_block(end); let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]); let val_type = layout.llvm_type(bx); - let val_addr = if is_indirect { - bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) - } else { - val_addr - }; + let val_addr = + if is_indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr }; bx.load(val_type, val_addr, layout.align.abi) } @@ -414,6 +413,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>( let in_reg = bx.append_sibling_block("va_arg.in_reg"); let in_mem = bx.append_sibling_block("va_arg.in_mem"); let end = bx.append_sibling_block("va_arg.end"); + let ptr_align_abi = dl.pointer_align().abi; // FIXME: vector ABI not yet supported. let target_ty_size = bx.cx.size_of(target_ty).bytes(); @@ -435,7 +435,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>( bx.switch_to_block(in_reg); // Work out the address of the value in the register save area. - let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, dl.pointer_align.abi); + let reg_ptr_v = bx.load(bx.type_ptr(), reg_save_area, ptr_align_abi); let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8)); let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding)); let reg_addr = bx.ptradd(reg_ptr_v, reg_off); @@ -449,15 +449,14 @@ fn emit_s390x_va_arg<'ll, 'tcx>( bx.switch_to_block(in_mem); // Work out the address of the value in the argument overflow area. - let arg_ptr_v = - bx.load(bx.type_ptr(), overflow_arg_area, bx.tcx().data_layout.pointer_align.abi); + let arg_ptr_v = bx.load(bx.type_ptr(), overflow_arg_area, ptr_align_abi); let arg_off = bx.const_u64(padding); let mem_addr = bx.ptradd(arg_ptr_v, arg_off); // Update the argument overflow area pointer. let arg_size = bx.cx().const_u64(padded_size); let new_arg_ptr_v = bx.inbounds_ptradd(arg_ptr_v, arg_size); - bx.store(new_arg_ptr_v, overflow_arg_area, dl.pointer_align.abi); + bx.store(new_arg_ptr_v, overflow_arg_area, ptr_align_abi); bx.br(end); // Return the appropriate result. @@ -465,7 +464,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>( let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]); let val_type = layout.llvm_type(bx); let val_addr = - if indirect { bx.load(bx.cx.type_ptr(), val_addr, dl.pointer_align.abi) } else { val_addr }; + if indirect { bx.load(bx.cx.type_ptr(), val_addr, ptr_align_abi) } else { val_addr }; bx.load(val_type, val_addr, layout.align.abi) } @@ -607,7 +606,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( // loads than necessary. Can we clean this up? let reg_save_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * unsigned_int_offset + ptr_offset)); - let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align.abi); + let reg_save_area_v = bx.load(bx.type_ptr(), reg_save_area_ptr, dl.pointer_align().abi); let reg_addr = match layout.layout.backend_repr() { BackendRepr::Scalar(scalar) => match scalar.primitive() { @@ -749,10 +748,11 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>( layout: TyAndLayout<'tcx, Ty<'tcx>>, ) -> &'ll Value { let dl = bx.cx.data_layout(); + let ptr_align_abi = dl.data_layout().pointer_align().abi; let overflow_arg_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.const_usize(8)); - let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, dl.pointer_align.abi); + let overflow_arg_area_v = bx.load(bx.type_ptr(), overflow_arg_area_ptr, ptr_align_abi); // AMD64-ABI 3.5.7p5: Step 7. Align l->overflow_arg_area upwards to a 16 // byte boundary if alignment needed by type exceeds 8 byte boundary. // It isn't stated explicitly in the standard, but in practice we use @@ -771,7 +771,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>( let size_in_bytes = layout.layout.size().bytes(); let offset = bx.const_i32(size_in_bytes.next_multiple_of(8) as i32); let overflow_arg_area = bx.inbounds_ptradd(overflow_arg_area_v, offset); - bx.store(overflow_arg_area, overflow_arg_area_ptr, dl.pointer_align.abi); + bx.store(overflow_arg_area, overflow_arg_area_ptr, ptr_align_abi); mem_addr } @@ -803,6 +803,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( let from_stack = bx.append_sibling_block("va_arg.from_stack"); let from_regsave = bx.append_sibling_block("va_arg.from_regsave"); let end = bx.append_sibling_block("va_arg.end"); + let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi; // (*va).va_ndx let va_reg_offset = 4; @@ -825,12 +826,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( bx.switch_to_block(from_regsave); // update va_ndx - bx.store(offset_next, offset_ptr, bx.tcx().data_layout.pointer_align.abi); + bx.store(offset_next, offset_ptr, ptr_align_abi); // (*va).va_reg let regsave_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(va_reg_offset)); - let regsave_area = - bx.load(bx.type_ptr(), regsave_area_ptr, bx.tcx().data_layout.pointer_align.abi); + let regsave_area = bx.load(bx.type_ptr(), regsave_area_ptr, ptr_align_abi); let regsave_value_ptr = bx.inbounds_ptradd(regsave_area, offset); bx.br(end); @@ -849,11 +849,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( // va_ndx = offset_next_corrected; let offset_next_corrected = bx.add(offset_next, bx.const_i32(slot_size)); // update va_ndx - bx.store(offset_next_corrected, offset_ptr, bx.tcx().data_layout.pointer_align.abi); + bx.store(offset_next_corrected, offset_ptr, ptr_align_abi); // let stack_value_ptr = unsafe { (*va).va_stk.byte_add(offset_corrected) }; let stack_area_ptr = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(0)); - let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, bx.tcx().data_layout.pointer_align.abi); + let stack_area = bx.load(bx.type_ptr(), stack_area_ptr, ptr_align_abi); let stack_value_ptr = bx.inbounds_ptradd(stack_area, offset_corrected); bx.br(end); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 8330e4f7af0..d2a64ec2993 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1208,7 +1208,7 @@ fn start_executing_work<B: ExtraBackendMethods>( split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, - pointer_size: tcx.data_layout.pointer_size, + pointer_size: tcx.data_layout.pointer_size(), invocation_temp: sess.invocation_temp.clone(), }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 102d4ea2fa6..18581f854b6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -200,7 +200,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target)); if let Some(entry_idx) = vptr_entry_idx { - let ptr_size = bx.data_layout().pointer_size; + let ptr_size = bx.data_layout().pointer_size(); let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes(); load_vtable(bx, old_info, bx.type_ptr(), vtable_byte_offset, source, true) } else { @@ -577,8 +577,8 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Va // Params for UEFI let param_handle = bx.get_param(0); let param_system_table = bx.get_param(1); - let ptr_size = bx.tcx().data_layout.pointer_size; - let ptr_align = bx.tcx().data_layout.pointer_align.abi; + let ptr_size = bx.tcx().data_layout.pointer_size(); + let ptr_align = bx.tcx().data_layout.pointer_align().abi; let arg_argc = bx.const_int(bx.cx().type_isize(), 2); let arg_argv = bx.alloca(2 * ptr_size, ptr_align); bx.store(param_handle, arg_argv, ptr_align); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index be63bb8ac59..ff454427871 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -4,7 +4,7 @@ use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_attr_data_structures::{ - AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, UsedBy, find_attr, + AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, UsedBy, find_attr, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -109,14 +109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let hir::Attribute::Parsed(p) = attr { match p { - AttributeKind::Repr { reprs, first_span: _ } => { - codegen_fn_attrs.alignment = reprs - .iter() - .filter_map( - |(r, _)| if let ReprAttr::ReprAlign(x) = r { Some(*x) } else { None }, - ) - .max(); - } AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, AttributeKind::ExportName { name, .. } => { codegen_fn_attrs.export_name = Some(*name); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 086c069745c..e042fe1f819 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -457,7 +457,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { } else if arg.as_encoded_bytes().ends_with(b".rlib") { let rlib_path = Path::new(&arg); let dir = rlib_path.parent().unwrap(); - let filename = rlib_path.file_name().unwrap().to_owned(); + let filename = rlib_path.file_stem().unwrap().to_owned(); if let Some(ArgGroup::Rlibs(parent, rlibs)) = args.last_mut() { if parent == dir { rlibs.push(filename); @@ -471,7 +471,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { args.push(ArgGroup::Regular(arg)); } } - let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap(); + let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+").unwrap(); self.command.args(args.into_iter().map(|arg_group| { match arg_group { // SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid. @@ -494,7 +494,11 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { Err(_) => false, }; let mut arg = dir.into_os_string(); - arg.push("/{"); + arg.push("/"); + let needs_braces = rlibs.len() >= 2; + if needs_braces { + arg.push("{"); + } let mut first = true; for mut rlib in rlibs { if !first { @@ -513,7 +517,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { } arg.push(rlib); } - arg.push("}.rlib"); + if needs_braces { + arg.push("}"); + } + arg.push(".rlib"); arg } } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 3a11ce6befb..2aa5c3c27ea 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -27,7 +27,7 @@ impl<'a, 'tcx> VirtualIndex { debug!("get_fn({llvtable:?}, {ty:?}, {self:?})"); let llty = bx.fn_ptr_backend_type(fn_abi); - let ptr_size = bx.data_layout().pointer_size; + let ptr_size = bx.data_layout().pointer_size(); let vtable_byte_offset = self.0 * ptr_size.bytes(); load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, nonnull) @@ -63,7 +63,7 @@ impl<'a, 'tcx> VirtualIndex { debug!("get_int({:?}, {:?})", llvtable, self); let llty = bx.type_isize(); - let ptr_size = bx.data_layout().pointer_size; + let ptr_size = bx.data_layout().pointer_size(); let vtable_byte_offset = self.0 * ptr_size.bytes(); load_vtable(bx, llvtable, llty, vtable_byte_offset, ty, false) @@ -115,7 +115,7 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref)); let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory(); let vtable_const = cx.const_data_from_alloc(vtable_allocation); - let align = cx.data_layout().pointer_align.abi; + let align = cx.data_layout().pointer_align().abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable); @@ -133,7 +133,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty: Ty<'tcx>, nonnull: bool, ) -> Bx::Value { - let ptr_align = bx.data_layout().pointer_align.abi; + let ptr_align = bx.data_layout().pointer_align().abi; if bx.cx().sess().opts.unstable_opts.virtual_function_elimination && bx.cx().sess().lto() == Lto::Fat diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 9da4b8cc8fd..beaf8950978 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -326,7 +326,7 @@ fn prefix_and_suffix<'tcx>( fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { let mut signature = String::with_capacity(64); - let ptr_type = match tcx.data_layout.pointer_size.bits() { + let ptr_type = match tcx.data_layout.pointer_size().bits() { 32 => "i32", 64 => "i64", other => bug!("wasm pointer size cannot be {other} bits"), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 43726e93252..4af4e1e6a61 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1135,7 +1135,7 @@ fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let range = scalar.valid_range(bx.cx()); bx.assume_integer_range(imm, backend_ty, range); } - abi::Primitive::Pointer(abi::AddressSpace::DATA) + abi::Primitive::Pointer(abi::AddressSpace::ZERO) if !scalar.valid_range(bx.cx()).contains(0) => { bx.assume_nonnull(imm); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 08e1877f0eb..4bd4b493009 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -19,7 +19,7 @@ use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine}; use crate::const_eval::CheckAlignment; use crate::interpret::{ CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind, - InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, create_static_alloc, + InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc, intern_const_alloc_recursive, interp_ok, throw_exhaust, }; use crate::{CTRL_C_RECEIVED, errors}; @@ -76,7 +76,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( cid.instance, body, &ret.clone().into(), - StackPopCleanup::Root { cleanup: false }, + ReturnContinuation::Stop { cleanup: false }, )?; ecx.storage_live_for_always_live_locals()?; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 76fa744361a..52fc898192a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -331,10 +331,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { fn load_mir( ecx: &InterpCx<'tcx, Self>, instance: ty::InstanceKind<'tcx>, - ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { + ) -> &'tcx mir::Body<'tcx> { match instance { - ty::InstanceKind::Item(def) => interp_ok(ecx.tcx.mir_for_ctfe(def)), - _ => interp_ok(ecx.tcx.instance_mir(instance)), + ty::InstanceKind::Item(def) => ecx.tcx.mir_for_ctfe(def), + _ => ecx.tcx.instance_mir(instance), } } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ebaa5a97a4a..ad3e02580f3 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -15,7 +15,7 @@ use tracing::{info, instrument, trace}; use super::{ CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, - Projectable, Provenance, ReturnAction, Scalar, StackPopCleanup, StackPopInfo, interp_ok, + Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, StackPopInfo, interp_ok, throw_ub, throw_ub_custom, throw_unsup_format, }; use crate::fluent_generated as fluent; @@ -340,7 +340,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, destination: &PlaceTy<'tcx, M::Provenance>, - mut stack_pop: StackPopCleanup, + mut cont: ReturnContinuation, ) -> InterpResult<'tcx> { // Compute callee information. // FIXME: for variadic support, do we have to somehow determine callee's extra_args? @@ -365,15 +365,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if !callee_fn_abi.can_unwind { // The callee cannot unwind, so force the `Unreachable` unwind handling. - match &mut stack_pop { - StackPopCleanup::Root { .. } => {} - StackPopCleanup::Goto { unwind, .. } => { + match &mut cont { + ReturnContinuation::Stop { .. } => {} + ReturnContinuation::Goto { unwind, .. } => { *unwind = mir::UnwindAction::Unreachable; } } } - self.push_stack_frame_raw(instance, body, destination, stack_pop)?; + self.push_stack_frame_raw(instance, body, destination, cont)?; // If an error is raised here, pop the frame again to get an accurate backtrace. // To this end, we wrap it all in a `try` block. @@ -617,7 +617,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &args, with_caller_location, destination, - StackPopCleanup::Goto { ret: target, unwind }, + ReturnContinuation::Goto { ret: target, unwind }, ) } // `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be @@ -755,8 +755,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`, // as the latter "executes" the goto to the return block, but we don't want to, // only the tail called function should return to the current return block. - let StackPopInfo { return_action, return_to_block, return_place } = self - .pop_stack_frame_raw(false, |_this, _return_place| { + let StackPopInfo { return_action, return_cont, return_place } = + self.pop_stack_frame_raw(false, |_this, _return_place| { // This function's return value is just discarded, the tail-callee will fill in the return place instead. interp_ok(()) })?; @@ -764,7 +764,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(return_action, ReturnAction::Normal); // Take the "stack pop cleanup" info, and use that to initiate the next call. - let StackPopCleanup::Goto { ret, unwind } = return_to_block else { + let ReturnContinuation::Goto { ret, unwind } = return_cont else { bug!("can't tailcall as root"); }; @@ -896,23 +896,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Normal return, figure out where to jump. if unwinding { // Follow the unwind edge. - match stack_pop_info.return_to_block { - StackPopCleanup::Goto { unwind, .. } => { + match stack_pop_info.return_cont { + ReturnContinuation::Goto { unwind, .. } => { // This must be the very last thing that happens, since it can in fact push a new stack frame. self.unwind_to_block(unwind) } - StackPopCleanup::Root { .. } => { - panic!("encountered StackPopCleanup::Root when unwinding!") + ReturnContinuation::Stop { .. } => { + panic!("encountered ReturnContinuation::Stop when unwinding!") } } } else { // Follow the normal return edge. - match stack_pop_info.return_to_block { - StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret), - StackPopCleanup::Root { .. } => { + match stack_pop_info.return_cont { + ReturnContinuation::Goto { ret, .. } => self.return_to_block(ret), + ReturnContinuation::Stop { .. } => { assert!( self.stack().is_empty(), - "only the bottommost frame can have StackPopCleanup::Root" + "only the bottommost frame can have ReturnContinuation::Stop" ); interp_ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 46c784b41c6..068d6369f87 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -272,7 +272,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let def = instance.def_id(); &self.tcx.promoted_mir(def)[promoted] } else { - M::load_mir(self, instance)? + M::load_mir(self, instance) }; // do not continue if typeck errors occurred (can only occur in local crate) if let Some(err) = body.tainted_by_errors { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 35ec303f961..844c19fea2d 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -189,8 +189,8 @@ pub trait Machine<'tcx>: Sized { fn load_mir( ecx: &InterpCx<'tcx, Self>, instance: ty::InstanceKind<'tcx>, - ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { - interp_ok(ecx.tcx.instance_mir(instance)) + ) -> &'tcx mir::Body<'tcx> { + ecx.tcx.instance_mir(instance) } /// Entry point to all function calls. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index c97d53a45de..524023b8104 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1233,7 +1233,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResult<'tcx> { - self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val) + self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size()), val) } /// Mark the given sub-range (relative to this allocation reference) as uninitialized. @@ -1285,7 +1285,7 @@ impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Pr /// `offset` is relative to this allocation reference, not the base of the allocation. pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> { self.read_scalar( - alloc_range(offset, self.tcx.data_layout().pointer_size), + alloc_range(offset, self.tcx.data_layout().pointer_size()), /*read_provenance*/ true, ) } diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index f8b3c92debb..8303f891f98 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -36,7 +36,7 @@ pub use self::operand::{ImmTy, Immediate, OpTy}; pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable}; use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; -pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo}; +pub use self::stack::{Frame, FrameInfo, LocalState, ReturnContinuation, StackPopInfo}; pub(crate) use self::util::create_static_alloc; pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 543d68d7f45..b6ba069526c 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -72,8 +72,8 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { //////////////////////////////////////////////////////////////////////////////// // Return place and locals //////////////////////////////////////////////////////////////////////////////// - /// Work to perform when returning from this function. - return_to_block: StackPopCleanup, + /// Where to continue when returning from this function. + return_cont: ReturnContinuation, /// The location where the result of the current stack frame should be written to, /// and its layout in the caller. This place is to be interpreted relative to the @@ -106,19 +106,19 @@ pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { pub(super) loc: Either<mir::Location, Span>, } +/// Where and how to continue when returning/unwinding from the current function. #[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these -pub enum StackPopCleanup { +pub enum ReturnContinuation { /// Jump to the next block in the caller, or cause UB if None (that's a function - /// that may never return). Also store layout of return place so - /// we can validate it at that layout. + /// that may never return). /// `ret` stores the block we jump to on a normal return, while `unwind` /// stores the block used for cleanup during unwinding. Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction }, - /// The root frame of the stack: nowhere else to jump to. + /// The root frame of the stack: nowhere else to jump to, so we stop. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away /// the entire `ecx` when it is done). - Root { cleanup: bool }, + Stop { cleanup: bool }, } /// Return type of [`InterpCx::pop_stack_frame_raw`]. @@ -127,8 +127,8 @@ pub struct StackPopInfo<'tcx, Prov: Provenance> { /// stack frame. pub return_action: ReturnAction, - /// [`return_to_block`](Frame::return_to_block) of the popped stack frame. - pub return_to_block: StackPopCleanup, + /// [`return_cont`](Frame::return_cont) of the popped stack frame. + pub return_cont: ReturnContinuation, /// [`return_place`](Frame::return_place) of the popped stack frame. pub return_place: PlaceTy<'tcx, Prov>, @@ -255,7 +255,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> { Frame { body: self.body, instance: self.instance, - return_to_block: self.return_to_block, + return_cont: self.return_cont, return_place: self.return_place, locals: self.locals, loc: self.loc, @@ -350,20 +350,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// the arguments or local variables. /// /// The high-level version of this is `init_stack_frame`. - #[instrument(skip(self, body, return_place, return_to_block), level = "debug")] + #[instrument(skip(self, body, return_place, return_cont), level = "debug")] pub(crate) fn push_stack_frame_raw( &mut self, instance: ty::Instance<'tcx>, body: &'tcx mir::Body<'tcx>, return_place: &PlaceTy<'tcx, M::Provenance>, - return_to_block: StackPopCleanup, + return_cont: ReturnContinuation, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); // We can push a `Root` frame if and only if the stack is empty. debug_assert_eq!( self.stack().is_empty(), - matches!(return_to_block, StackPopCleanup::Root { .. }) + matches!(return_cont, ReturnContinuation::Stop { .. }) ); // First push a stack frame so we have access to `instantiate_from_current_frame` and other @@ -373,7 +373,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let pre_frame = Frame { body, loc: Right(body.span), // Span used for errors caused during preamble. - return_to_block, + return_cont, return_place: return_place.clone(), locals, instance, @@ -429,15 +429,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { copy_ret_val(self, &frame.return_place)?; } - let return_to_block = frame.return_to_block; + let return_cont = frame.return_cont; let return_place = frame.return_place.clone(); // Cleanup: deallocate locals. // Usually we want to clean up (deallocate locals), but in a few rare cases we don't. // We do this while the frame is still on the stack, so errors point to the callee. - let cleanup = match return_to_block { - StackPopCleanup::Goto { .. } => true, - StackPopCleanup::Root { cleanup, .. } => cleanup, + let cleanup = match return_cont { + ReturnContinuation::Goto { .. } => true, + ReturnContinuation::Stop { cleanup, .. } => cleanup, }; let return_action = if cleanup { @@ -455,7 +455,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ReturnAction::NoCleanup }; - interp_ok(StackPopInfo { return_action, return_to_block, return_place }) + interp_ok(StackPopInfo { return_action, return_cont, return_place }) } /// In the current stack frame, mark all locals as live that are not arguments and don't have diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 1b4db7adc27..881aa679156 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -142,7 +142,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("generic-activity", EventFilter::GENERIC_ACTIVITIES), ("query-provider", EventFilter::QUERY_PROVIDERS), ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), - ("query-cache-hit-count", EventFilter::QUERY_CACHE_HITS), + ("query-cache-hit-count", EventFilter::QUERY_CACHE_HIT_COUNTS), ("query-blocked", EventFilter::QUERY_BLOCKED), ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), ("query-keys", EventFilter::QUERY_KEYS), diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl index d68dba0be5e..ad2e206260d 100644 --- a/compiler/rustc_errors/messages.ftl +++ b/compiler/rustc_errors/messages.ftl @@ -41,5 +41,8 @@ errors_target_invalid_bits = errors_target_invalid_bits_size = {$err} +errors_target_invalid_datalayout_pointer_spec = + unknown pointer specification `{$err}` in datalayout string + errors_target_missing_alignment = missing alignment for `{$cause}` in "data-layout" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 8b59ba9984c..eeb9ac28808 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -374,6 +374,10 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { TargetDataLayoutErrors::InvalidBitsSize { err } => { Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err) } + TargetDataLayoutErrors::UnknownPointerSpecification { err } => { + Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec) + .with_arg("err", err) + } } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 69ad15c6081..381d780077d 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -3,7 +3,6 @@ //! This module contains the code for creating and emitting diagnostics. // tidy-alphabetical-start -#![allow(incomplete_features)] #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::direct_use_of_rustc_type_ir)] diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 52cdcc5c747..89547088f50 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -373,17 +373,10 @@ pub fn compile_declarative_macro( node_id: NodeId, edition: Edition, ) -> (SyntaxExtension, usize) { + let is_local = node_id != DUMMY_NODE_ID; let mk_syn_ext = |expander| { - SyntaxExtension::new( - sess, - SyntaxExtensionKind::LegacyBang(expander), - span, - Vec::new(), - edition, - ident.name, - attrs, - node_id != DUMMY_NODE_ID, - ) + let kind = SyntaxExtensionKind::LegacyBang(expander); + SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local) }; let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0); @@ -393,7 +386,8 @@ pub fn compile_declarative_macro( let body = macro_def.body.tokens.clone(); let mut p = Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS); - // Don't abort iteration early, so that multiple errors can be reported. + // Don't abort iteration early, so that multiple errors can be reported. We only abort early on + // parse failures we can't recover from. let mut guar = None; let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err()); @@ -402,20 +396,11 @@ pub fn compile_declarative_macro( while p.token != token::Eof { let lhs_tt = p.parse_token_tree(); let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition); - // We don't handle errors here, the driver will abort after parsing/expansion. We can - // report every error in every macro this way. - check_emission(check_lhs_nt_follows(sess, node_id, &lhs_tt)); - check_emission(check_lhs_no_empty_seq(sess, slice::from_ref(&lhs_tt))); + check_emission(check_lhs(sess, node_id, &lhs_tt)); if let Err(e) = p.expect(exp!(FatArrow)) { return dummy_syn_ext(e.emit()); } - if p.token == token::Eof { - let err_sp = p.token.span.shrink_to_hi(); - let guar = sess - .dcx() - .struct_span_err(err_sp, "macro definition ended unexpectedly") - .with_span_label(err_sp, "expected right-hand side of macro rule") - .emit(); + if let Some(guar) = check_no_eof(sess, &p, "expected right-hand side of macro rule") { return dummy_syn_ext(guar); } let rhs_tt = p.parse_token_tree(); @@ -454,13 +439,32 @@ pub fn compile_declarative_macro( } // Return the number of rules for unused rule linting, if this is a local macro. - let nrules = if node_id != DUMMY_NODE_ID { rules.len() } else { 0 }; + let nrules = if is_local { rules.len() } else { 0 }; let expander = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules }); (mk_syn_ext(expander), nrules) } +fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> { + if p.token == token::Eof { + let err_sp = p.token.span.shrink_to_hi(); + let guar = sess + .dcx() + .struct_span_err(err_sp, "macro definition ended unexpectedly") + .with_span_label(err_sp, msg) + .emit(); + return Some(guar); + } + None +} + +fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> { + let e1 = check_lhs_nt_follows(sess, node_id, lhs); + let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs)); + e1.and(e2) +} + fn check_lhs_nt_follows( sess: &Session, node_id: NodeId, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 459fe5935e0..df010f87098 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -831,7 +831,7 @@ pub enum LifetimeRes { /// Id of the introducing place. That can be: /// - an item's id, for the item's generic parameters; /// - a TraitRef's ref_id, identifying the `for<...>` binder; - /// - a BareFn type's id. + /// - a FnPtr type's id. /// /// This information is used for impl-trait lifetime captures, to know when to or not to /// capture any given lifetime. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 559a771931e..0f6f81d7964 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3526,7 +3526,7 @@ impl PrimTy { } #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub struct BareFnTy<'hir> { +pub struct FnPtrTy<'hir> { pub safety: Safety, pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], @@ -3645,8 +3645,8 @@ pub enum TyKind<'hir, Unambig = ()> { Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). Ref(&'hir Lifetime, MutTy<'hir>), - /// A bare function (e.g., `fn(usize) -> bool`). - BareFn(&'hir BareFnTy<'hir>), + /// A function pointer (e.g., `fn(usize) -> bool`). + FnPtr(&'hir FnPtrTy<'hir>), /// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`). UnsafeBinder(&'hir UnsafeBinderTy<'hir>), /// The never type (`!`). @@ -4498,7 +4498,7 @@ pub enum ForeignItemKind<'hir> { /// /// All argument idents are actually always present (i.e. `Some`), but /// `&[Option<Ident>]` is used because of code paths shared with `TraitFn` - /// and `BareFnTy`. The sharing is due to all of these cases not allowing + /// and `FnPtrTy`. The sharing is due to all of these cases not allowing /// arbitrary patterns for parameters. Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>), /// A foreign static item (`static ext: u8`). diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index a0bc318e2ca..1bb8f7ad894 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1001,7 +1001,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) - TyKind::Tup(tuple_element_types) => { walk_list!(visitor, visit_ty_unambig, tuple_element_types); } - TyKind::BareFn(ref function_declaration) => { + TyKind::FnPtr(ref function_declaration) => { walk_list!(visitor, visit_generic_param, function_declaration.generic_params); try_visit!(visitor.visit_fn_decl(function_declaration.decl)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bd89d010a3c..f4bbf03f0c2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -768,15 +768,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), check_static_inhabited(tcx, def_id); check_static_linkage(tcx, def_id); res = res.and(wfcheck::check_static_item(tcx, def_id)); - - // Only `Node::Item` and `Node::ForeignItem` still have HIR based - // checks. Returning early here does not miss any checks and - // avoids this query from having a direct dependency edge on the HIR - return res; } - DefKind::Const => {} + DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)), _ => unreachable!(), } + // Only `Node::Item` and `Node::ForeignItem` still have HIR based + // checks. Returning early here does not miss any checks and + // avoids this query from having a direct dependency edge on the HIR + return res; } DefKind::Enum => { tcx.ensure_ok().generics_of(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0a3e018b79a..428d627ad6f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -290,7 +290,6 @@ pub(super) fn check_item<'tcx>( res } hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl), - hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span), hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false), hir::ItemKind::Union(..) => check_type_defn(tcx, item, true), hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true), @@ -1185,7 +1184,8 @@ pub(super) fn check_static_item( ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item_id, |wfcx| { let ty = tcx.type_of(item_id).instantiate_identity(); - let item_ty = wfcx.deeply_normalize(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), ty); + let span = tcx.ty_span(item_id); + let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); let is_foreign_item = tcx.is_foreign_item(item_id); @@ -1194,7 +1194,7 @@ pub(super) fn check_static_item( !matches!(tail.kind(), ty::Foreign(_)) }; - wfcx.register_wf_obligation(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); + wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); if forbid_unsized { let span = tcx.def_span(item_id); wfcx.register_bound( @@ -1216,7 +1216,6 @@ pub(super) fn check_static_item( && !tcx.is_thread_local_static(item_id.to_def_id()); if should_check_for_sync { - let span = tcx.def_span(item_id); wfcx.register_bound( traits::ObligationCause::new( span, @@ -1232,13 +1231,10 @@ pub(super) fn check_static_item( }) } -fn check_const_item( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - ty_span: Span, -) -> Result<(), ErrorGuaranteed> { +pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, def_id, |wfcx| { let ty = tcx.type_of(def_id).instantiate_identity(); + let ty_span = tcx.ty_span(def_id); let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into()); @@ -1505,7 +1501,7 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: let cause = traits::ObligationCause::new( sp, wfcx.body_def_id, - ObligationCauseCode::WhereClause(def_id.to_def_id(), DUMMY_SP), + ObligationCauseCode::WhereClause(def_id.to_def_id(), sp), ); Obligation::new(tcx, cause, wfcx.param_env, pred) }); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 25064c327d0..a185291887d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -198,7 +198,7 @@ fn placeholder_type_error_diag<'cx, 'tcx>( let mut is_const_or_static = false; if let Some(hir_ty) = hir_ty - && let hir::TyKind::BareFn(_) = hir_ty.kind + && let hir::TyKind::FnPtr(_) = hir_ty.kind { is_fn = true; diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 573af01a62d..31e9c3b80fb 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -454,7 +454,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S type Result = ControlFlow<Span>; fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) -> ControlFlow<Span> { match ty.kind { - hir::TyKind::BareFn(..) => { + hir::TyKind::FnPtr(..) => { self.outer_index.shift_in(1); let res = intravisit::walk_ty(self, ty); self.outer_index.shift_out(1); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index a0d1273eb85..8d7ac7db67b 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -704,7 +704,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match ty.kind { - hir::TyKind::BareFn(c) => { + hir::TyKind::FnPtr(c) => { let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c .generic_params .iter() @@ -728,8 +728,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { where_bound_origin: None, }; self.with(scope, |this| { - // a bare fn has no bounds, so everything - // contained within is scoped within its binder. + // a FnPtr has no bounds, so everything within is scoped within its binder intravisit::walk_ty(this, ty); }); } @@ -758,8 +757,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { where_bound_origin: None, }; self.with(scope, |this| { - // a bare fn has no bounds, so everything - // contained within is scoped within its binder. + // everything within is scoped within its binder intravisit::walk_ty(this, ty); }); } @@ -1419,7 +1417,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`", // Other items are fine. hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()), - hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => { + hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(_), .. }) => { "higher-ranked lifetime from function pointer" } hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => { diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index ef789743e06..3f928fd056e 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -393,9 +393,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let params = if let Some(generics) = node.generics() { generics.params } else if let hir::Node::Ty(ty) = node - && let hir::TyKind::BareFn(bare_fn) = ty.kind + && let hir::TyKind::FnPtr(fn_ptr) = ty.kind { - bare_fn.generic_params + fn_ptr.generic_params } else { &[] }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 82e5f65476f..5088c63702e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -21,8 +21,8 @@ pub(crate) fn validate_cmse_abi<'tcx>( ExternAbi::CmseNonSecureCall => { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { - span: bare_fn_span, - kind: hir::TyKind::BareFn(bare_fn_ty), + span: fn_ptr_span, + kind: hir::TyKind::FnPtr(fn_ptr_ty), .. }) = hir_node else { @@ -49,18 +49,18 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(Err(index)) => { // fn(x: u32, u32, u32, u16, y: u16) -> u32, // ^^^^^^ - let span = if let Some(ident) = bare_fn_ty.param_idents[index] { - ident.span.to(bare_fn_ty.decl.inputs[index].span) + let span = if let Some(ident) = fn_ptr_ty.param_idents[index] { + ident.span.to(fn_ptr_ty.decl.inputs[index].span) } else { - bare_fn_ty.decl.inputs[index].span + fn_ptr_ty.decl.inputs[index].span } - .to(bare_fn_ty.decl.inputs.last().unwrap().span); - let plural = bare_fn_ty.param_idents.len() - index != 1; + .to(fn_ptr_ty.decl.inputs.last().unwrap().span); + let plural = fn_ptr_ty.param_idents.len() - index != 1; dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { - dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + dcx.emit_err(errors::CmseCallGeneric { span: *fn_ptr_span }); } } } @@ -68,12 +68,12 @@ pub(crate) fn validate_cmse_abi<'tcx>( match is_valid_cmse_output(tcx, fn_sig) { Ok(true) => {} Ok(false) => { - let span = bare_fn_ty.decl.output.span(); + let span = fn_ptr_ty.decl.output.span(); dcx.emit_err(errors::CmseOutputStackSpill { span, abi }); } Err(layout_err) => { if should_emit_generic_error(abi, layout_err) { - dcx.emit_err(errors::CmseCallGeneric { span: *bare_fn_span }); + dcx.emit_err(errors::CmseCallGeneric { span: *fn_ptr_span }); } } }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 434375060df..20d165897e2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2402,7 +2402,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::Tup(fields) => { Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t))) } - hir::TyKind::BareFn(bf) => { + hir::TyKind::FnPtr(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span); Ty::new_fn_ptr( @@ -2660,28 +2660,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?output_ty); let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); - let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); + let fn_ptr_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); - if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) = + if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::FnPtr(fn_ptr_ty), span, .. }) = tcx.hir_node(hir_id) { - check_abi(tcx, hir_id, *span, bare_fn_ty.abi); + check_abi(tcx, hir_id, *span, fn_ptr_ty.abi); } // reject function types that violate cmse ABI requirements - cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); + cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, fn_ptr_ty); - if !bare_fn_ty.references_error() { + if !fn_ptr_ty.references_error() { // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. // // Example: // for<'a> fn() -> &'a str <-- 'a is bad // for<'a> fn(&'a String) -> &'a str <-- 'a is ok - let inputs = bare_fn_ty.inputs(); + let inputs = fn_ptr_ty.inputs(); let late_bound_in_args = tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned())); - let output = bare_fn_ty.output(); + let output = fn_ptr_ty.output(); let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output); self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| { @@ -2695,7 +2695,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); } - bare_fn_ty + fn_ptr_ty } /// Given a fn_hir_id for a impl function, suggest the type that is found on the diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index c523a03e012..3a525021f6f 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -405,7 +405,7 @@ impl<'a> State<'a> { } self.pclose(); } - hir::TyKind::BareFn(f) => { + hir::TyKind::FnPtr(f) => { self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_idents); } hir::TyKind::UnsafeBinder(unsafe_binder) => { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 8c1399aec14..7611f8ac3e1 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); - // If the callee is a bare function or a closure, then we're all set. + // If the callee is a function pointer or a closure, then we're all set. match *adjusted_ty.kind() { ty::FnDef(..) | ty::FnPtr(..) => { let adjustments = self.adjust_steps(autoderef); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 2bc007b3ad4..4e4bf8a5562 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -184,9 +184,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() + for param in [ + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ] + .into_iter() + .flatten() { if self.blame_specific_arg_if_possible( error, diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 285e2912937..e562c583313 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -14,9 +14,7 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 3b0a36186b6..653559009cc 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::borrow::Cow; use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5e05b58146e..21148833eaf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,4 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] use std::num::NonZero; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index ad7686b3e5b..bc9badbb232 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -431,7 +431,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, hir::AmbigArg>) { - if let hir::TyKind::BareFn(hir::BareFnTy { param_idents, .. }) = &ty.kind { + if let hir::TyKind::FnPtr(hir::FnPtrTy { param_idents, .. }) = &ty.kind { for param_ident in *param_idents { if let Some(param_ident) = param_ident { self.check_snake_case(cx, "variable", param_ident); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index ea5485d8e5d..e41bc8f852e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1577,7 +1577,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'tcx> { fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) { debug!(?ty); - if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind + if let hir::TyKind::FnPtr(hir::FnPtrTy { abi, .. }) = ty.kind && !abi.is_rustic_abi() { self.spans.push(ty.span); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0627f70507c..d3942a1c816 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1312,7 +1312,7 @@ impl EarlyLintPass for UnusedParens { None => true, } } - ast::TyKind::BareFn(b) => { + ast::TyKind::FnPtr(b) => { !self.with_self_ty_parens || b.generic_params.is_empty() } _ => true, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index d4a05fbbbc5..cc33764e485 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1275,7 +1275,7 @@ extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M, // // Otherwise I'll apologize in advance, it probably requires a relatively // significant investment on your part to "truly understand" what's going on -// here. Not saying I do myself, but it took me awhile staring at LLVM's source +// here. Not saying I do myself, but it took me a while staring at LLVM's source // and various online resources about ThinLTO to make heads or tails of all // this. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index a0f45974089..f140ab4755b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,5 +1,3 @@ -#![allow(rustc::usage_of_ty_tykind)] - /// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index d7a8dce0536..6c07e49734a 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -239,8 +239,16 @@ pub fn provide(providers: &mut Providers) { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir_opt_ident_span(hir_id) }; + providers.ty_span = |tcx, def_id| { + let node = tcx.hir_node_by_def_id(def_id); + match node.ty() { + Some(ty) => ty.span, + None => bug!("{def_id:?} doesn't have a type: {node:#?}"), + } + }; providers.fn_arg_idents = |tcx, def_id| { - if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() { + let node = tcx.hir_node_by_def_id(def_id); + if let Some(body_id) = node.body_id() { tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), @@ -249,7 +257,7 @@ pub fn provide(providers: &mut Providers) { | Node::ForeignItem(&ForeignItem { kind: ForeignItemKind::Fn(_, idents, _), .. - }) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id)) + }) = node { idents } else { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 16edc240544..fb941977528 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -142,7 +142,7 @@ impl<'tcx> ConstValue<'tcx> { // The reference itself is stored behind an indirection. // Load the reference, and then load the actual slice contents. let a = tcx.global_alloc(alloc_id).unwrap_memory().inner(); - let ptr_size = tcx.data_layout.pointer_size; + let ptr_size = tcx.data_layout.pointer_size(); if a.size() < offset + 2 * ptr_size { // (partially) dangling reference return None; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index d2cadc96b63..f039849d1bb 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -519,7 +519,7 @@ impl Allocation { let mut bytes = alloc_bytes(&*self.bytes, self.align)?; // Adjust provenance of pointers stored in this allocation. let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); - let ptr_size = cx.data_layout().pointer_size.bytes_usize(); + let ptr_size = cx.data_layout().pointer_size().bytes_usize(); let endian = cx.data_layout().endian; for &(offset, alloc_id) in self.provenance.ptrs().iter() { let idx = offset.bytes_usize(); @@ -709,7 +709,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap(); if read_provenance { - assert_eq!(range.size, cx.data_layout().pointer_size); + assert_eq!(range.size, cx.data_layout().pointer_size()); // When reading data with provenance, the easy case is finding provenance exactly where we // are reading, then we can put data and provenance back together and return that. @@ -782,7 +782,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> // See if we have to also store some provenance. if let Some(provenance) = provenance { - assert_eq!(range.size, cx.data_layout().pointer_size); + assert_eq!(range.size, cx.data_layout().pointer_size()); self.provenance.insert_ptr(range.start, provenance, cx); } diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 63608947eb3..9c6e1664386 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -71,7 +71,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // We have to go back `pointer_size - 1` bytes, as that one would still overlap with // the beginning of this range. let adjusted_start = Size::from_bytes( - range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1), + range.start.bytes().saturating_sub(cx.data_layout().pointer_size().bytes() - 1), ); adjusted_start..range.end() } @@ -142,7 +142,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { } pub fn insert_ptr(&mut self, offset: Size, prov: Prov, cx: &impl HasDataLayout) { - debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size), cx)); + debug_assert!(self.range_empty(alloc_range(offset, cx.data_layout().pointer_size()), cx)); self.ptrs.insert(offset, prov); } @@ -160,6 +160,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { debug_assert!(self.bytes.is_none()); } + let pointer_size = cx.data_layout().pointer_size(); + // For the ptr-sized part, find the first (inclusive) and last (exclusive) byte of // provenance that overlaps with the given range. let (first, last) = { @@ -172,10 +174,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much // colder than the early return above, so it's worth it. let provenance = self.range_ptrs_get(range, cx); - ( - provenance.first().unwrap().0, - provenance.last().unwrap().0 + cx.data_layout().pointer_size, - ) + (provenance.first().unwrap().0, provenance.last().unwrap().0 + pointer_size) }; // We need to handle clearing the provenance from parts of a pointer. @@ -192,7 +191,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { } } if last > end { - let begin_of_last = last - cx.data_layout().pointer_size; + let begin_of_last = last - pointer_size; if !Prov::OFFSET_IS_ADDR { // We can't split up the provenance into less than a pointer. return Err(AllocError::OverwritePartialPointer(begin_of_last)); @@ -255,7 +254,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // shift offsets from source allocation to destination allocation (offset - src.start) + dest_offset // `Size` operations }; - let ptr_size = cx.data_layout().pointer_size; + let ptr_size = cx.data_layout().pointer_size(); // # Pointer-sized provenances // Get the provenances that are entirely within this range. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index da9e5bdbadd..0b2645013ba 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -297,7 +297,7 @@ impl<'tcx> GlobalAlloc<'tcx> { match self { GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space, GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => { - AddressSpace::DATA + AddressSpace::ZERO } } } @@ -380,7 +380,7 @@ impl<'tcx> GlobalAlloc<'tcx> { GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE), GlobalAlloc::VTable(..) => { // No data to be accessed here. But vtables are pointer-aligned. - return (Size::ZERO, tcx.data_layout.pointer_align.abi); + return (Size::ZERO, tcx.data_layout.pointer_align().abi); } } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 0ff14f15c13..e25ff7651f6 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -16,7 +16,7 @@ pub trait PointerArithmetic: HasDataLayout { #[inline(always)] fn pointer_size(&self) -> Size { - self.data_layout().pointer_size + self.data_layout().pointer_size() } #[inline(always)] diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 8092f634dc8..90df29bb7e3 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -167,7 +167,7 @@ impl<Prov> Scalar<Prov> { #[inline] pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self { - Self::from_uint(i, cx.data_layout().pointer_size) + Self::from_uint(i, cx.data_layout().pointer_offset()) } #[inline] @@ -205,7 +205,7 @@ impl<Prov> Scalar<Prov> { #[inline] pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self { - Self::from_int(i, cx.data_layout().pointer_size) + Self::from_int(i, cx.data_layout().pointer_offset()) } #[inline] @@ -393,7 +393,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> { /// Converts the scalar to produce a machine-pointer-sized unsigned integer. /// Fails if the scalar is a pointer. pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { - let b = self.to_uint(cx.data_layout().pointer_size)?; + let b = self.to_uint(cx.data_layout().pointer_size())?; interp_ok(u64::try_from(b).unwrap()) } @@ -433,7 +433,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> { /// Converts the scalar to produce a machine-pointer-sized signed integer. /// Fails if the scalar is a pointer. pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> { - let b = self.to_int(cx.data_layout().pointer_size)?; + let b = self.to_int(cx.data_layout().pointer_size())?; interp_ok(i64::try_from(b).unwrap()) } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6b262a27500..e9f3fb6ac8d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1753,7 +1753,7 @@ pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( let mut i = Size::ZERO; let mut line_start = Size::ZERO; - let ptr_size = tcx.data_layout.pointer_size; + let ptr_size = tcx.data_layout.pointer_size(); let mut ascii = String::new(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 17a29c9ae4b..9af5683ff75 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1452,6 +1452,13 @@ rustc_queries! { feedable } + /// Gets the span for the type of the definition. + /// Panics if it is not a definition that has a single type. + query ty_span(def_id: LocalDefId) -> Span { + desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + query lookup_stability(def_id: DefId) -> Option<attr::Stability> { desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index aa2ee756bc5..c498e6b3c83 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -97,9 +97,7 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), pub enum SelectionCandidate<'tcx> { /// A built-in implementation for the `Sized` trait. This is preferred /// over all other candidates. - SizedCandidate { - has_nested: bool, - }, + SizedCandidate, /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. @@ -107,10 +105,7 @@ pub enum SelectionCandidate<'tcx> { /// The most notable examples are `Copy` and `Clone`. This is also /// used for the `DiscriminantKind` and `Pointee` trait, both of which have /// an associated type. - BuiltinCandidate { - /// `false` if there are no *further* obligations. - has_nested: bool, - }, + BuiltinCandidate, /// Implementation of transmutability trait. TransmutabilityCandidate, diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index b087ae25486..6ee76b94507 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -252,7 +252,7 @@ impl ScalarInt { #[inline] pub fn try_from_target_usize(i: impl Into<u128>, tcx: TyCtxt<'_>) -> Option<Self> { - Self::try_from_uint(i, tcx.data_layout.pointer_size) + Self::try_from_uint(i, tcx.data_layout.pointer_size()) } /// Try to convert this ScalarInt to the raw underlying bits. @@ -328,7 +328,7 @@ impl ScalarInt { #[inline] pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 { - self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap() + self.to_uint(tcx.data_layout.pointer_size()).try_into().unwrap() } #[inline] @@ -402,7 +402,7 @@ impl ScalarInt { #[inline] pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 { - self.to_int(tcx.data_layout.pointer_size).try_into().unwrap() + self.to_int(tcx.data_layout.pointer_size()).try_into().unwrap() } #[inline] diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 09379d9d805..809717513c7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1067,7 +1067,7 @@ where if let Some(variant) = data_variant { // FIXME(erikdesjardins): handle non-default addrspace ptr sizes // (requires passing in the expected address space from the caller) - let ptr_end = offset + Primitive::Pointer(AddressSpace::DATA).size(cx); + let ptr_end = offset + Primitive::Pointer(AddressSpace::ZERO).size(cx); for i in 0..variant.fields.count() { let field_start = variant.fields.offset(i); if field_start <= offset { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1dba4a7b040..4e078847815 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1842,7 +1842,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } // Pointer types ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => { - let data = int.to_bits(self.tcx().data_layout.pointer_size); + let data = int.to_bits(self.tcx().data_layout.pointer_size()); self.typed_value( |this| { write!(this, "0x{data:x}")?; diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 74b6a840a2e..6fc19c82342 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -106,8 +106,8 @@ pub(super) fn vtable_allocation_provider<'tcx>( let size = layout.size.bytes(); let align = layout.align.abi.bytes(); - let ptr_size = tcx.data_layout.pointer_size; - let ptr_align = tcx.data_layout.pointer_align.abi; + let ptr_size = tcx.data_layout.pointer_size(); + let ptr_align = tcx.data_layout.pointer_align().abi; let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap(); let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit, ()); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 405d47c7c79..5a5456aedc2 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -936,7 +936,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { valtree } - Err(ErrorHandled::Reported(..)) => return self.cfg.start_new_block().unit(), + Err(ErrorHandled::Reported(..)) => { + return block.unit(); + } Err(ErrorHandled::TooGeneric(_)) => { self.tcx.dcx().emit_fatal(ConstContinueBadConst { span: constant.span }); } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 8e218a380e9..52e6f2d3e1a 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -20,7 +20,7 @@ pub(crate) fn lit_to_const<'tcx>( let trunc = |n, width: ty::UintTy| { let width = width - .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) + .normalize(tcx.data_layout.pointer_size().bits().try_into().unwrap()) .bit_width() .unwrap(); let width = Size::from_bits(width); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 08f3ce5fd67..93a81f0dca5 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -155,15 +155,8 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>( let recursion_limit = tcx.recursion_limit() / 2; let mut involved = FxHashSet::default(); let typing_env = ty::TypingEnv::post_analysis(tcx, root); - let Ok(Some(root_instance)) = ty::Instance::try_resolve( - tcx, - typing_env, - root.to_def_id(), - ty::GenericArgs::identity_for_item(tcx, root.to_def_id()), - ) else { - trace!("cannot resolve, skipping"); - return involved.into(); - }; + let root_instance = + ty::Instance::new_raw(root.to_def_id(), ty::GenericArgs::identity_for_item(tcx, root)); if !should_recurse(tcx, root_instance) { trace!("cannot walk, skipping"); return involved.into(); diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 03b6f9b7ff3..d3b4b99e932 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -322,8 +322,8 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) { // visited before `local`, and we just have to copy the representing local. let head = copies[rhs]; - // Do not unify two borrowed locals. - if borrowed_classes.contains(local) && borrowed_classes.contains(head) { + // Do not unify borrowed locals. + if borrowed_classes.contains(local) || borrowed_classes.contains(head) { continue; } diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 8ea535599c9..2050c5f9608 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,7 +1,6 @@ //! The main parser interface. // tidy-alphabetical-start -#![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 1df0ccbd8af..e0f810d8c1e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1677,7 +1677,7 @@ impl<'a> Parser<'a> { let hi = self.prev_token.span.shrink_to_hi(); BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } } } - TyKind::Ptr(..) | TyKind::BareFn(..) => { + TyKind::Ptr(..) | TyKind::FnPtr(..) => { BadTypePlusSub::ForgotParen { span: ty.span.to(self.prev_token.span) } } _ => BadTypePlusSub::ExpectPath { span: ty.span }, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index cfc0399b0ca..2787be46f33 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1293,8 +1293,10 @@ impl<'a> Parser<'a> { let kind = if pat { let guar = self .dcx() - .struct_span_err(blk_span, "`inline_const_pat` has been removed") - .with_help("use a named `const`-item or an `if`-guard instead") + .struct_span_err(blk_span, "const blocks cannot be used as patterns") + .with_help( + "use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead", + ) .emit(); ExprKind::Err(guar) } else { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 0c57a8cc5e1..a997be3405d 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -2,7 +2,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy, + self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy, @@ -283,14 +283,14 @@ impl<'a> Parser<'a> { TyKind::Infer } else if self.check_fn_front_matter(false, Case::Sensitive) { // Function pointer type - self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)? + self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)? } else if self.check_keyword(exp!(For)) { // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; if self.check_fn_front_matter(false, Case::Sensitive) { - self.parse_ty_bare_fn( + self.parse_ty_fn_ptr( lo, lifetime_defs, Some(self.prev_token.span.shrink_to_lo()), @@ -665,7 +665,7 @@ impl<'a> Parser<'a> { Ok(TyKind::Typeof(expr)) } - /// Parses a function pointer type (`TyKind::BareFn`). + /// Parses a function pointer type (`TyKind::FnPtr`). /// ```ignore (illustrative) /// [unsafe] [extern "ABI"] fn (S) -> T /// // ^~~~~^ ^~~~^ ^~^ ^ @@ -674,7 +674,7 @@ impl<'a> Parser<'a> { /// // Function Style ABI Parameter types /// ``` /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers. - fn parse_ty_bare_fn( + fn parse_ty_fn_ptr( &mut self, lo: Span, mut params: ThinVec<GenericParam>, @@ -698,7 +698,7 @@ impl<'a> Parser<'a> { let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let decl_span = span_start.to(self.prev_token.span); - Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span }))) + Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span }))) } /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`). diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 8fdc06ee463..67b68e77d2b 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -267,6 +267,42 @@ pub fn check_builtin_meta_item( deny_unsafety: bool, ) { if !is_attr_template_compatible(&template, &meta.kind) { + // attrs with new parsers are locally validated so excluded here + if matches!( + name, + sym::inline + | sym::may_dangle + | sym::rustc_as_ptr + | sym::rustc_pub_transparent + | sym::rustc_const_stable_indirect + | sym::rustc_force_inline + | sym::rustc_confusables + | sym::rustc_skip_during_method_dispatch + | sym::rustc_pass_by_value + | sym::repr + | sym::align + | sym::deprecated + | sym::optimize + | sym::cold + | sym::target_feature + | sym::rustc_allow_const_fn_unstable + | sym::naked + | sym::no_mangle + | sym::non_exhaustive + | sym::path + | sym::ignore + | sym::must_use + | sym::track_caller + | sym::link_name + | sym::export_name + | sym::rustc_macro_transparency + | sym::link_section + | sym::rustc_layout_scalar_valid_range_start + | sym::rustc_layout_scalar_valid_range_end + | sym::no_implicit_prelude + ) { + return; + } emit_malformed_attribute(psess, style, meta.span, name, template); } @@ -282,42 +318,6 @@ fn emit_malformed_attribute( name: Symbol, template: AttributeTemplate, ) { - // attrs with new parsers are locally validated so excluded here - if matches!( - name, - sym::inline - | sym::may_dangle - | sym::rustc_as_ptr - | sym::rustc_pub_transparent - | sym::rustc_const_stable_indirect - | sym::rustc_force_inline - | sym::rustc_confusables - | sym::rustc_skip_during_method_dispatch - | sym::rustc_pass_by_value - | sym::repr - | sym::align - | sym::deprecated - | sym::optimize - | sym::cold - | sym::target_feature - | sym::rustc_allow_const_fn_unstable - | sym::naked - | sym::no_mangle - | sym::non_exhaustive - | sym::ignore - | sym::must_use - | sym::track_caller - | sym::link_name - | sym::export_name - | sym::rustc_macro_transparency - | sym::link_section - | sym::rustc_layout_scalar_valid_range_start - | sym::rustc_layout_scalar_valid_range_end - | sym::no_implicit_prelude - ) { - return; - } - // Some of previously accepted forms were used in practice, // report them as warnings for now. let should_warn = |name| matches!(name, sym::doc | sym::link | sym::test | sym::bench); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5a94d01e088..46c21dcf67b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -13,6 +13,10 @@ passes_abi_ne = passes_abi_of = fn_abi_of({$fn_name}) = {$fn_abi} +passes_align_attr_application = + `#[align(...)]` should be applied to a function item + .label = not a function item + passes_align_should_be_repr_align = `#[align(...)]` is not supported on {$item} items .suggestion = use `#[repr(align(...))]` instead diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3fa5cdc36bc..9e4e78c1db6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -191,6 +191,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target, Target::Mod, ), + Attribute::Parsed(AttributeKind::Path(_, attr_span)) => { + self.check_generic_attr(hir_id, sym::path, *attr_span, target, Target::Mod) + } Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => { self.check_track_caller(hir_id, *attr_span, attrs, span, target) } @@ -1915,7 +1918,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks if the `#[align]` attributes on `item` are valid. fn check_align(&self, span: Span, target: Target, align: Align, repr_span: Span) { match target { - Target::Fn | Target::Method(_) => {} + Target::Fn | Target::Method(_) | Target::ForeignFn => {} Target::Struct | Target::Union | Target::Enum => { self.dcx().emit_err(errors::AlignShouldBeReprAlign { span: repr_span, @@ -1924,10 +1927,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } _ => { - self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { - hint_span: repr_span, - span, - }); + self.dcx().emit_err(errors::AlignAttrApplication { hint_span: repr_span, span }); } } @@ -2800,7 +2800,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { // resolution for the attribute macro error. const ATTRS_TO_CHECK: &[Symbol] = &[ sym::macro_export, - sym::path, sym::automatically_derived, sym::rustc_main, sym::derive, @@ -2822,6 +2821,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { }) = attr { (*first_attr_span, sym::repr) + } else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr { + (*span, sym::path) } else { continue; }; @@ -2946,8 +2947,8 @@ fn check_duplicates( fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool { matches!(&self_ty.kind, hir::TyKind::Tup([_])) - || if let hir::TyKind::BareFn(bare_fn_ty) = &self_ty.kind { - bare_fn_ty.decl.inputs.len() == 1 + || if let hir::TyKind::FnPtr(fn_ptr_ty) = &self_ty.kind { + fn_ptr_ty.decl.inputs.len() == 1 } else { false } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 3ede3c889c8..4ad615a2abf 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1838,3 +1838,12 @@ pub(crate) struct AlignShouldBeReprAlign { pub item: &'static str, pub align_bytes: u64, } + +#[derive(Diagnostic)] +#[diag(passes_align_attr_application)] +pub(crate) struct AlignAttrApplication { + #[primary_span] + pub hint_span: Span, + #[label] + pub span: Span, +} diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 40bc18939d6..e38c7b2cbf1 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -400,7 +400,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Array, Ptr, Ref, - BareFn, + FnPtr, UnsafeBinder, Never, Tup, @@ -674,7 +674,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Ptr, Ref, PinnedRef, - BareFn, + FnPtr, UnsafeBinder, Never, Tup, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 56d9f5bf785..a30655d32a7 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1070,7 +1070,7 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { if let TyKind::Never = t.kind { self.fully_stable = false; } - if let TyKind::BareFn(function) = t.kind { + if let TyKind::FnPtr(function) = t.kind { if extern_abi_stability(function.abi).is_err() { self.fully_stable = false; } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index b7d8af2c995..306d4dbc4b4 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -2,7 +2,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![allow(unused_parens)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(min_specialization)] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index a97e0eaa9c6..1238ce0125a 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -19,6 +19,7 @@ rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index eeb8cb893d7..f775cac149e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -18,6 +18,7 @@ use rustc_expand::base::ResolverExpand; use rustc_expand::expand::AstFragment; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; +use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; use rustc_middle::ty::Feed; @@ -1202,9 +1203,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) { if !ident.as_str().starts_with('_') { self.r.unused_macros.insert(def_id, (node_id, ident)); - for rule_i in 0..self.r.macro_map[&def_id.to_def_id()].nrules { - self.r.unused_macro_rules.entry(node_id).or_default().insert(rule_i); - } + let nrules = self.r.macro_map[&def_id.to_def_id()].nrules; + self.r.unused_macro_rules.insert(node_id, DenseBitSet::new_filled(nrules)); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 08c4a485f26..08629090bb1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -370,7 +370,7 @@ enum LifetimeRibKind { #[derive(Copy, Clone, Debug)] enum LifetimeBinderKind { - BareFnType, + FnPtrType, PolyTrait, WhereBound, Item, @@ -384,7 +384,7 @@ impl LifetimeBinderKind { fn descr(self) -> &'static str { use LifetimeBinderKind::*; match self { - BareFnType => "type", + FnPtrType => "type", PolyTrait => "bound", WhereBound => "bound", Item | ConstItem => "item", @@ -900,16 +900,16 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.diag_metadata.current_trait_object = Some(&bounds[..]); visit::walk_ty(self, ty) } - TyKind::BareFn(bare_fn) => { - let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo()); + TyKind::FnPtr(fn_ptr) => { + let span = ty.span.shrink_to_lo().to(fn_ptr.decl_span.shrink_to_lo()); self.with_generic_param_rib( - &bare_fn.generic_params, + &fn_ptr.generic_params, RibKind::Normal, ty.id, - LifetimeBinderKind::BareFnType, + LifetimeBinderKind::FnPtrType, span, |this| { - this.visit_generic_params(&bare_fn.generic_params, false); + this.visit_generic_params(&fn_ptr.generic_params, false); this.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { binder: ty.id, @@ -921,12 +921,8 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc false, // We don't need to deal with patterns in parameters, because // they are not possible for foreign or bodiless functions. - bare_fn - .decl - .inputs - .iter() - .map(|Param { ty, .. }| (None, &**ty)), - &bare_fn.decl.output, + fn_ptr.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), + &fn_ptr.decl.output, ) }, ); @@ -939,7 +935,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc &unsafe_binder.generic_params, RibKind::Normal, ty.id, - LifetimeBinderKind::BareFnType, + LifetimeBinderKind::FnPtrType, span, |this| { this.visit_generic_params(&unsafe_binder.generic_params, false); @@ -2976,7 +2972,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - if let LifetimeBinderKind::BareFnType + if let LifetimeBinderKind::FnPtrType | LifetimeBinderKind::WhereBound | LifetimeBinderKind::Function | LifetimeBinderKind::ImplBlock = generics_kind diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4022691995..fa04c8bc604 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3177,7 +3177,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let higher_ranked = matches!( kind, - LifetimeBinderKind::BareFnType + LifetimeBinderKind::FnPtrType | LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3f865d7c2da..f8ca20c568f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -57,6 +57,7 @@ use rustc_hir::def::{ use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::DisambiguatorState; use rustc_hir::{PrimTy, TraitCandidate}; +use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; @@ -1135,7 +1136,7 @@ pub struct Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>, unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>, /// A map from the macro to all its potentially unused arms. - unused_macro_rules: FxIndexMap<NodeId, UnordSet<usize>>, + unused_macro_rules: FxIndexMap<NodeId, DenseBitSet<usize>>, proc_macro_stubs: FxHashSet<LocalDefId>, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 9bc96403559..acbefe53422 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -334,7 +334,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) { if let Some(rules) = self.unused_macro_rules.get_mut(&id) { - rules.remove(&rule_i); + rules.remove(rule_i); } } @@ -359,7 +359,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let SyntaxExtensionKind::LegacyBang(ref ext) = m.ext.kind else { continue; }; - for &arm_i in unused_arms.to_sorted_stable_ord() { + for arm_i in unused_arms.iter() { if let Some((ident, rule_span)) = ext.get_unused_rule(arm_i) { self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index cbfe9e0da6a..62891eb4f26 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -278,7 +278,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { }; insert_atomic(sym::integer(i), align); if sess.target.pointer_width as u64 == i { - insert_atomic(sym::ptr, layout.pointer_align.abi); + insert_atomic(sym::ptr, layout.pointer_align().abi); } } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 8386fe8dab0..85bd8340c3c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -776,8 +776,15 @@ impl Session { pub fn must_emit_unwind_tables(&self) -> bool { // This is used to control the emission of the `uwtable` attribute on - // LLVM functions. + // LLVM functions. The `uwtable` attribute according to LLVM is: // + // This attribute indicates that the ABI being targeted requires that an + // unwind table entry be produced for this function even if we can show + // that no exceptions passes by it. This is normally the case for the + // ELF x86-64 abi, but it can be disabled for some compilation units. + // + // Typically when we're compiling with `-C panic=abort` we don't need + // `uwtable` because we can't generate any exceptions! // Unwind tables are needed when compiling with `-C panic=unwind`, but // LLVM won't omit unwind tables unless the function is also marked as // `nounwind`, so users are allowed to disable `uwtable` emission. diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index fc9f411ac3c..b7ea478f731 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -13,7 +13,4 @@ rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -scoped-tls = "1.0" -serde = { version = "1.0.125", features = [ "derive" ] } -tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/alloc.rs index ecaf3571896..fd3cf24edb5 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/alloc.rs @@ -11,14 +11,14 @@ use rustc_middle::mir::interpret::{ use rustc_middle::ty::{Ty, layout}; use super::{SmirCtxt, Tables}; -use crate::rustc_smir::bridge::Allocation as _; -use crate::rustc_smir::{Bridge, SmirError}; +use crate::bridge::Allocation as _; +use crate::{Bridge, SmirError}; pub fn create_ty_and_layout<'tcx, B: Bridge>( cx: &SmirCtxt<'tcx, B>, ty: Ty<'tcx>, ) -> Result<TyAndLayout<'tcx, Ty<'tcx>>, &'tcx layout::LayoutError<'tcx>> { - use crate::rustc_smir::context::SmirTypingEnv; + use crate::context::SmirTypingEnv; cx.tcx.layout_of(cx.fully_monomorphized().as_query_input(ty)) } @@ -47,15 +47,12 @@ pub fn try_new_slice<'tcx, B: Bridge>( let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx); let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx); let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ()); + let ptr_size = cx.tcx.data_layout.pointer_size(); allocation - .write_scalar(&cx.tcx, alloc_range(Size::ZERO, cx.tcx.data_layout.pointer_size), scalar_ptr) + .write_scalar(&cx.tcx, alloc_range(Size::ZERO, ptr_size), scalar_ptr) .map_err(|e| B::Error::from_internal(e))?; allocation - .write_scalar( - &cx.tcx, - alloc_range(cx.tcx.data_layout.pointer_size, scalar_meta.size()), - scalar_meta, - ) + .write_scalar(&cx.tcx, alloc_range(ptr_size, scalar_meta.size()), scalar_meta) .map_err(|e| B::Error::from_internal(e))?; Ok(allocation) diff --git a/compiler/rustc_smir/src/rustc_smir/bridge.rs b/compiler/rustc_smir/src/bridge.rs index a31eb93d0e8..a31eb93d0e8 100644 --- a/compiler/rustc_smir/src/rustc_smir/bridge.rs +++ b/compiler/rustc_smir/src/bridge.rs diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/builder.rs index 2141053d09a..2141053d09a 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/builder.rs diff --git a/compiler/rustc_smir/src/rustc_smir/context/impls.rs b/compiler/rustc_smir/src/context/impls.rs index 89ae47143ef..fdefad2821b 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/impls.rs +++ b/compiler/rustc_smir/src/context/impls.rs @@ -25,8 +25,8 @@ use rustc_span::{FileNameDisplayPreference, Span, Symbol}; use rustc_target::callconv::FnAbi; use super::{SmirAllocRange, SmirCtxt, SmirTy, SmirTypingEnv}; -use crate::rustc_smir::builder::BodyBuilder; -use crate::rustc_smir::{Bridge, SmirError, Tables, filter_def_ids}; +use crate::builder::BodyBuilder; +use crate::{Bridge, SmirError, Tables, filter_def_ids}; impl<'tcx, B: Bridge> SmirTy<'tcx> for SmirCtxt<'tcx, B> { fn new_foreign(&self, def_id: DefId) -> ty::Ty<'tcx> { @@ -112,7 +112,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> { } pub fn target_pointer_size(&self) -> usize { - self.tcx.data_layout.pointer_size.bits().try_into().unwrap() + self.tcx.data_layout.pointer_size().bits().try_into().unwrap() } pub fn entry_fn(&self) -> Option<DefId> { @@ -426,7 +426,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> { /// Evaluate constant as a target usize. pub fn eval_target_usize(&self, cnst: MirConst<'tcx>) -> Result<u64, B::Error> { - use crate::rustc_smir::context::SmirTypingEnv; + use crate::context::SmirTypingEnv; cnst.try_eval_target_usize(self.tcx, self.fully_monomorphized()) .ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } @@ -436,10 +436,7 @@ impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> { .ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } - pub(crate) fn try_new_const_zst( - &self, - ty_internal: Ty<'tcx>, - ) -> Result<MirConst<'tcx>, B::Error> { + pub fn try_new_const_zst(&self, ty_internal: Ty<'tcx>) -> Result<MirConst<'tcx>, B::Error> { let size = self .tcx .layout_of(self.fully_monomorphized().as_query_input(ty_internal)) diff --git a/compiler/rustc_smir/src/rustc_smir/context/mod.rs b/compiler/rustc_smir/src/context/mod.rs index 38743e5f7d3..da20be2a4b3 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/mod.rs +++ b/compiler/rustc_smir/src/context/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOfHelpers}; use rustc_middle::ty::{Ty, TyCtxt}; -use crate::rustc_smir::{Bridge, SmirError}; +use crate::{Bridge, SmirError}; mod impls; mod traits; @@ -18,7 +18,7 @@ pub use traits::*; /// Provides direct access to rustc's internal queries. /// -/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through +/// `SmirInterface` must go through /// this context to obtain rustc-level information. pub struct SmirCtxt<'tcx, B: Bridge> { pub tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_smir/src/rustc_smir/context/traits.rs b/compiler/rustc_smir/src/context/traits.rs index 19e09016cdd..8483bee4aad 100644 --- a/compiler/rustc_smir/src/rustc_smir/context/traits.rs +++ b/compiler/rustc_smir/src/context/traits.rs @@ -8,31 +8,6 @@ use rustc_middle::ty; use rustc_middle::ty::Ty; use rustc_span::def_id::DefId; -pub trait SmirExistentialProjection<'tcx> { - fn new_from_args( - &self, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - term: ty::Term<'tcx>, - ) -> ty::ExistentialProjection<'tcx>; -} - -pub trait SmirExistentialTraitRef<'tcx> { - fn new_from_args( - &self, - trait_def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx>; -} - -pub trait SmirTraitRef<'tcx> { - fn new_from_args( - &self, - trait_def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx>; -} - pub trait SmirTy<'tcx> { fn new_foreign(&self, def_id: DefId) -> Ty<'tcx>; } diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 067adda791d..fbebf98df7d 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -1,4 +1,9 @@ -//! The WIP stable interface to rustc internals. +//! Crate that implements what will become the rustc side of Stable MIR. +//! +//! This crate is responsible for building Stable MIR components from internal components. +//! +//! This crate is not intended to be invoked directly by users. +//! This crate is the public API of rustc that will be invoked by the `stable_mir` crate. //! //! For more information see <https://github.com/rust-lang/project-stable-mir> //! @@ -18,8 +23,283 @@ #![feature(sized_hierarchy)] // tidy-alphabetical-end -pub mod rustc_internal; +use std::cell::RefCell; +use std::fmt::Debug; +use std::hash::Hash; +use std::ops::Index; + +use bridge::*; +use context::SmirCtxt; +use rustc_data_structures::fx::{self, FxIndexMap}; +use rustc_middle::mir; +use rustc_middle::mir::interpret::AllocId; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; +use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; + +pub mod alloc; +pub mod bridge; +mod builder; +pub mod context; + +#[deprecated(note = "please use `stable_mir::rustc_internal` instead")] +pub mod rustc_internal {} + +/// A container which is used for TLS. +pub struct SmirContainer<'tcx, B: Bridge> { + pub tables: RefCell<Tables<'tcx, B>>, + pub cx: RefCell<SmirCtxt<'tcx, B>>, +} + +pub struct Tables<'tcx, B: Bridge> { + pub def_ids: IndexMap<DefId, B::DefId>, + pub alloc_ids: IndexMap<AllocId, B::AllocId>, + pub spans: IndexMap<rustc_span::Span, B::Span>, + pub types: IndexMap<Ty<'tcx>, B::Ty>, + pub instances: IndexMap<ty::Instance<'tcx>, B::InstanceDef>, + pub ty_consts: IndexMap<ty::Const<'tcx>, B::TyConstId>, + pub mir_consts: IndexMap<mir::Const<'tcx>, B::MirConstId>, + pub layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>, +} + +impl<'tcx, B: Bridge> Default for Tables<'tcx, B> { + fn default() -> Self { + Self { + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), + types: IndexMap::default(), + instances: IndexMap::default(), + ty_consts: IndexMap::default(), + mir_consts: IndexMap::default(), + layouts: IndexMap::default(), + } + } +} + +impl<'tcx, B: Bridge> Index<B::DefId> for Tables<'tcx, B> { + type Output = DefId; + + #[inline(always)] + fn index(&self, index: B::DefId) -> &Self::Output { + &self.def_ids[index] + } +} + +impl<'tcx, B: Bridge> Tables<'tcx, B> { + pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty { + self.types.create_or_fetch(ty) + } + + pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId { + self.ty_consts.create_or_fetch(ct) + } + + pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId { + self.mir_consts.create_or_fetch(constant) + } + + pub fn create_def_id(&mut self, did: DefId) -> B::DefId { + self.def_ids.create_or_fetch(did) + } + + pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId { + self.alloc_ids.create_or_fetch(aid) + } + + pub fn create_span(&mut self, span: Span) -> B::Span { + self.spans.create_or_fetch(span) + } + + pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef { + self.instances.create_or_fetch(instance) + } + + pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout { + self.layouts.create_or_fetch(layout) + } + + pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem { + B::CrateItem::new(self.create_def_id(did)) + } + + pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef { + B::AdtDef::new(self.create_def_id(did)) + } + + pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef { + B::ForeignModuleDef::new(self.create_def_id(did)) + } + + pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef { + B::ForeignDef::new(self.create_def_id(did)) + } + + pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef { + B::FnDef::new(self.create_def_id(did)) + } + + pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef { + B::ClosureDef::new(self.create_def_id(did)) + } + + pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef { + B::CoroutineDef::new(self.create_def_id(did)) + } + + pub fn coroutine_closure_def( + &mut self, + did: rustc_span::def_id::DefId, + ) -> B::CoroutineClosureDef { + B::CoroutineClosureDef::new(self.create_def_id(did)) + } + + pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef { + B::AliasDef::new(self.create_def_id(did)) + } + + pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef { + B::ParamDef::new(self.create_def_id(did)) + } + + pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef { + B::BrNamedDef::new(self.create_def_id(did)) + } + + pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef { + B::TraitDef::new(self.create_def_id(did)) + } + + pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef { + B::GenericDef::new(self.create_def_id(did)) + } + + pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef { + B::ConstDef::new(self.create_def_id(did)) + } + + pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef { + B::ImplDef::new(self.create_def_id(did)) + } + + pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef { + B::RegionDef::new(self.create_def_id(did)) + } + + pub fn coroutine_witness_def( + &mut self, + did: rustc_span::def_id::DefId, + ) -> B::CoroutineWitnessDef { + B::CoroutineWitnessDef::new(self.create_def_id(did)) + } + + pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef { + B::AssocDef::new(self.create_def_id(did)) + } + + pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef { + B::OpaqueDef::new(self.create_def_id(did)) + } + + pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov { + B::Prov::new(self.create_alloc_id(aid)) + } + + pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef { + B::StaticDef::new(self.create_def_id(did)) + } +} + +/// A trait defining types that are used to emulate StableMIR components, which is really +/// useful when programming in stable_mir-agnostic settings. +pub trait Bridge: Sized { + type DefId: Copy + Debug + PartialEq + IndexedVal; + type AllocId: Copy + Debug + PartialEq + IndexedVal; + type Span: Copy + Debug + PartialEq + IndexedVal; + type Ty: Copy + Debug + PartialEq + IndexedVal; + type InstanceDef: Copy + Debug + PartialEq + IndexedVal; + type TyConstId: Copy + Debug + PartialEq + IndexedVal; + type MirConstId: Copy + Debug + PartialEq + IndexedVal; + type Layout: Copy + Debug + PartialEq + IndexedVal; + + type Error: SmirError; + type CrateItem: CrateItem<Self>; + type AdtDef: AdtDef<Self>; + type ForeignModuleDef: ForeignModuleDef<Self>; + type ForeignDef: ForeignDef<Self>; + type FnDef: FnDef<Self>; + type ClosureDef: ClosureDef<Self>; + type CoroutineDef: CoroutineDef<Self>; + type CoroutineClosureDef: CoroutineClosureDef<Self>; + type AliasDef: AliasDef<Self>; + type ParamDef: ParamDef<Self>; + type BrNamedDef: BrNamedDef<Self>; + type TraitDef: TraitDef<Self>; + type GenericDef: GenericDef<Self>; + type ConstDef: ConstDef<Self>; + type ImplDef: ImplDef<Self>; + type RegionDef: RegionDef<Self>; + type CoroutineWitnessDef: CoroutineWitnessDef<Self>; + type AssocDef: AssocDef<Self>; + type OpaqueDef: OpaqueDef<Self>; + type Prov: Prov<Self>; + type StaticDef: StaticDef<Self>; + + type Allocation: Allocation<Self>; +} + +pub trait IndexedVal { + fn to_val(index: usize) -> Self; + + fn to_index(&self) -> usize; +} + +/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra +/// safety features added. +pub struct IndexMap<K, V> { + index_map: fx::FxIndexMap<K, V>, +} + +impl<K, V> Default for IndexMap<K, V> { + fn default() -> Self { + Self { index_map: FxIndexMap::default() } + } +} + +impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> { + pub fn create_or_fetch(&mut self, key: K) -> V { + let len = self.index_map.len(); + let v = self.index_map.entry(key).or_insert(V::to_val(len)); + *v + } +} + +impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V> + for IndexMap<K, V> +{ + type Output = K; -pub mod rustc_smir; + fn index(&self, index: V) -> &Self::Output { + let (k, v) = self.index_map.get_index(index.to_index()).unwrap(); + assert_eq!(*v, index, "Provided value doesn't match with indexed value"); + k + } +} -pub mod stable_mir; +/// Iterate over the definitions of the given crate. +pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T> +where + F: FnMut(DefId) -> Option<T>, +{ + if krate == LOCAL_CRATE { + tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect() + } else { + let num_definitions = tcx.num_extern_def_ids(krate); + (0..num_definitions) + .filter_map(move |i| { + let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) }; + func(def_id) + }) + .collect() + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs deleted file mode 100644 index e8b7a3fec09..00000000000 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ /dev/null @@ -1,286 +0,0 @@ -//! Module that implements what will become the rustc side of Stable MIR. - -//! This module is responsible for building Stable MIR components from internal components. -//! -//! This module is not intended to be invoked directly by users. It will eventually -//! become the public API of rustc that will be invoked by the `stable_mir` crate. -//! -//! For now, we are developing everything inside `rustc`, thus, we keep this module private. - -use std::cell::RefCell; -use std::fmt::Debug; -use std::hash::Hash; -use std::ops::Index; - -use bridge::*; -use context::SmirCtxt; -use rustc_data_structures::fx::{self, FxIndexMap}; -use rustc_middle::mir; -use rustc_middle::mir::interpret::AllocId; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::Span; -use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; - -pub mod alloc; -pub mod bridge; -mod builder; -pub mod context; - -/// A container which is used for TLS. -pub struct SmirContainer<'tcx, B: Bridge> { - pub tables: RefCell<Tables<'tcx, B>>, - pub cx: RefCell<SmirCtxt<'tcx, B>>, -} - -pub struct Tables<'tcx, B: Bridge> { - pub def_ids: IndexMap<DefId, B::DefId>, - pub alloc_ids: IndexMap<AllocId, B::AllocId>, - pub spans: IndexMap<rustc_span::Span, B::Span>, - pub types: IndexMap<Ty<'tcx>, B::Ty>, - pub instances: IndexMap<ty::Instance<'tcx>, B::InstanceDef>, - pub ty_consts: IndexMap<ty::Const<'tcx>, B::TyConstId>, - pub mir_consts: IndexMap<mir::Const<'tcx>, B::MirConstId>, - pub layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>, -} - -impl<'tcx, B: Bridge> Default for Tables<'tcx, B> { - fn default() -> Self { - Self { - def_ids: IndexMap::default(), - alloc_ids: IndexMap::default(), - spans: IndexMap::default(), - types: IndexMap::default(), - instances: IndexMap::default(), - ty_consts: IndexMap::default(), - mir_consts: IndexMap::default(), - layouts: IndexMap::default(), - } - } -} - -impl<'tcx, B: Bridge> Index<B::DefId> for Tables<'tcx, B> { - type Output = DefId; - - #[inline(always)] - fn index(&self, index: B::DefId) -> &Self::Output { - &self.def_ids[index] - } -} - -impl<'tcx, B: Bridge> Tables<'tcx, B> { - pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty { - self.types.create_or_fetch(ty) - } - - pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId { - self.ty_consts.create_or_fetch(ct) - } - - pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId { - self.mir_consts.create_or_fetch(constant) - } - - pub fn create_def_id(&mut self, did: DefId) -> B::DefId { - self.def_ids.create_or_fetch(did) - } - - pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId { - self.alloc_ids.create_or_fetch(aid) - } - - pub fn create_span(&mut self, span: Span) -> B::Span { - self.spans.create_or_fetch(span) - } - - pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef { - self.instances.create_or_fetch(instance) - } - - pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout { - self.layouts.create_or_fetch(layout) - } - - pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem { - B::CrateItem::new(self.create_def_id(did)) - } - - pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef { - B::AdtDef::new(self.create_def_id(did)) - } - - pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef { - B::ForeignModuleDef::new(self.create_def_id(did)) - } - - pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef { - B::ForeignDef::new(self.create_def_id(did)) - } - - pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef { - B::FnDef::new(self.create_def_id(did)) - } - - pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef { - B::ClosureDef::new(self.create_def_id(did)) - } - - pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef { - B::CoroutineDef::new(self.create_def_id(did)) - } - - pub fn coroutine_closure_def( - &mut self, - did: rustc_span::def_id::DefId, - ) -> B::CoroutineClosureDef { - B::CoroutineClosureDef::new(self.create_def_id(did)) - } - - pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef { - B::AliasDef::new(self.create_def_id(did)) - } - - pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef { - B::ParamDef::new(self.create_def_id(did)) - } - - pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef { - B::BrNamedDef::new(self.create_def_id(did)) - } - - pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef { - B::TraitDef::new(self.create_def_id(did)) - } - - pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef { - B::GenericDef::new(self.create_def_id(did)) - } - - pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef { - B::ConstDef::new(self.create_def_id(did)) - } - - pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef { - B::ImplDef::new(self.create_def_id(did)) - } - - pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef { - B::RegionDef::new(self.create_def_id(did)) - } - - pub fn coroutine_witness_def( - &mut self, - did: rustc_span::def_id::DefId, - ) -> B::CoroutineWitnessDef { - B::CoroutineWitnessDef::new(self.create_def_id(did)) - } - - pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef { - B::AssocDef::new(self.create_def_id(did)) - } - - pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef { - B::OpaqueDef::new(self.create_def_id(did)) - } - - pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov { - B::Prov::new(self.create_alloc_id(aid)) - } - - pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef { - B::StaticDef::new(self.create_def_id(did)) - } -} - -/// A trait defining types that are used to emulate StableMIR components, which is really -/// useful when programming in stable_mir-agnostic settings. -pub trait Bridge: Sized { - type DefId: Copy + Debug + PartialEq + IndexedVal; - type AllocId: Copy + Debug + PartialEq + IndexedVal; - type Span: Copy + Debug + PartialEq + IndexedVal; - type Ty: Copy + Debug + PartialEq + IndexedVal; - type InstanceDef: Copy + Debug + PartialEq + IndexedVal; - type TyConstId: Copy + Debug + PartialEq + IndexedVal; - type MirConstId: Copy + Debug + PartialEq + IndexedVal; - type Layout: Copy + Debug + PartialEq + IndexedVal; - - type Error: SmirError; - type CrateItem: CrateItem<Self>; - type AdtDef: AdtDef<Self>; - type ForeignModuleDef: ForeignModuleDef<Self>; - type ForeignDef: ForeignDef<Self>; - type FnDef: FnDef<Self>; - type ClosureDef: ClosureDef<Self>; - type CoroutineDef: CoroutineDef<Self>; - type CoroutineClosureDef: CoroutineClosureDef<Self>; - type AliasDef: AliasDef<Self>; - type ParamDef: ParamDef<Self>; - type BrNamedDef: BrNamedDef<Self>; - type TraitDef: TraitDef<Self>; - type GenericDef: GenericDef<Self>; - type ConstDef: ConstDef<Self>; - type ImplDef: ImplDef<Self>; - type RegionDef: RegionDef<Self>; - type CoroutineWitnessDef: CoroutineWitnessDef<Self>; - type AssocDef: AssocDef<Self>; - type OpaqueDef: OpaqueDef<Self>; - type Prov: Prov<Self>; - type StaticDef: StaticDef<Self>; - - type Allocation: Allocation<Self>; -} - -pub trait IndexedVal { - fn to_val(index: usize) -> Self; - - fn to_index(&self) -> usize; -} - -/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra -/// safety features added. -pub struct IndexMap<K, V> { - index_map: fx::FxIndexMap<K, V>, -} - -impl<K, V> Default for IndexMap<K, V> { - fn default() -> Self { - Self { index_map: FxIndexMap::default() } - } -} - -impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> { - pub fn create_or_fetch(&mut self, key: K) -> V { - let len = self.index_map.len(); - let v = self.index_map.entry(key).or_insert(V::to_val(len)); - *v - } -} - -impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V> - for IndexMap<K, V> -{ - type Output = K; - - fn index(&self, index: V) -> &Self::Output { - let (k, v) = self.index_map.get_index(index.to_index()).unwrap(); - assert_eq!(*v, index, "Provided value doesn't match with indexed value"); - k - } -} - -/// Iterate over the definitions of the given crate. -pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T> -where - F: FnMut(DefId) -> Option<T>, -{ - if krate == LOCAL_CRATE { - tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect() - } else { - let num_definitions = tcx.num_extern_def_ids(krate); - (0..num_definitions) - .filter_map(move |i| { - let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) }; - func(def_id) - }) - .collect() - } -} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs deleted file mode 100644 index 70c09c12854..00000000000 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ /dev/null @@ -1,304 +0,0 @@ -//! Module that is temporarily parasitic on the `rustc_smir` crate, -//! -//! This module is designed to resolve circular dependency that would happen -//! if we gradually invert the dependency order between `rustc_smir` and `stable_mir`. -//! -//! Once refactoring is complete, we will migrate it back to the `stable_mir` crate. - -//! The WIP stable interface to rustc internals. -//! -//! For more information see <https://github.com/rust-lang/project-stable-mir> -//! -//! # Note -//! -//! This API is still completely unstable and subject to change. - -// #![doc( -// html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", -// test(attr(allow(unused_variables), deny(warnings))) -// )] -//! -//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to -//! interact with the compiler. -//! -//! The goal is to eventually be published on -//! [crates.io](https://crates.io). - -use std::fmt::Debug; -use std::{fmt, io}; - -pub(crate) use rustc_smir::IndexedVal; -use rustc_smir::Tables; -use rustc_smir::context::SmirCtxt; -use serde::Serialize; -use stable_mir::compiler_interface::with; -pub use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; -pub use stable_mir::error::*; -use stable_mir::mir::mono::StaticDef; -use stable_mir::mir::{Body, Mutability}; -use stable_mir::ty::{ - AssocItem, FnDef, ForeignModuleDef, ImplDef, ProvenanceMap, Span, TraitDef, Ty, -}; -use stable_mir::unstable::Stable; - -use crate::{rustc_smir, stable_mir}; - -pub mod abi; -mod alloc; -pub(crate) mod unstable; -#[macro_use] -pub mod crate_def; -pub mod compiler_interface; -#[macro_use] -pub mod error; -pub mod mir; -pub mod target; -pub mod ty; -pub mod visitor; - -/// Use String for now but we should replace it. -pub type Symbol = String; - -/// The number that identifies a crate. -pub type CrateNum = usize; - -impl Debug for DefId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish() - } -} - -impl IndexedVal for DefId { - fn to_val(index: usize) -> Self { - DefId(index) - } - - fn to_index(&self) -> usize { - self.0 - } -} - -/// A list of crate items. -pub type CrateItems = Vec<CrateItem>; - -/// A list of trait decls. -pub type TraitDecls = Vec<TraitDef>; - -/// A list of impl trait decls. -pub type ImplTraitDecls = Vec<ImplDef>; - -/// A list of associated items. -pub type AssocItems = Vec<AssocItem>; - -/// Holds information about a crate. -#[derive(Clone, PartialEq, Eq, Debug, Serialize)] -pub struct Crate { - pub id: CrateNum, - pub name: Symbol, - pub is_local: bool, -} - -impl Crate { - /// The list of foreign modules in this crate. - pub fn foreign_modules(&self) -> Vec<ForeignModuleDef> { - with(|cx| cx.foreign_modules(self.id)) - } - - /// The list of traits declared in this crate. - pub fn trait_decls(&self) -> TraitDecls { - with(|cx| cx.trait_decls(self.id)) - } - - /// The list of trait implementations in this crate. - pub fn trait_impls(&self) -> ImplTraitDecls { - with(|cx| cx.trait_impls(self.id)) - } - - /// Return a list of function definitions from this crate independent on their visibility. - pub fn fn_defs(&self) -> Vec<FnDef> { - with(|cx| cx.crate_functions(self.id)) - } - - /// Return a list of static items defined in this crate independent on their visibility. - pub fn statics(&self) -> Vec<StaticDef> { - with(|cx| cx.crate_statics(self.id)) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum ItemKind { - Fn, - Static, - Const, - Ctor(CtorKind), -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] -pub enum CtorKind { - Const, - Fn, -} - -pub type Filename = String; - -crate_def_with_ty! { - /// Holds information about an item in a crate. - #[derive(Serialize)] - pub CrateItem; -} - -impl CrateItem { - /// This will return the body of an item or panic if it's not available. - pub fn expect_body(&self) -> mir::Body { - with(|cx| cx.mir_body(self.0)) - } - - /// Return the body of an item if available. - pub fn body(&self) -> Option<mir::Body> { - with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) - } - - /// Check if a body is available for this item. - pub fn has_body(&self) -> bool { - with(|cx| cx.has_body(self.0)) - } - - pub fn span(&self) -> Span { - with(|cx| cx.span_of_an_item(self.0)) - } - - pub fn kind(&self) -> ItemKind { - with(|cx| cx.item_kind(*self)) - } - - pub fn requires_monomorphization(&self) -> bool { - with(|cx| cx.requires_monomorphization(self.0)) - } - - pub fn ty(&self) -> Ty { - with(|cx| cx.def_ty(self.0)) - } - - pub fn is_foreign_item(&self) -> bool { - with(|cx| cx.is_foreign_item(self.0)) - } - - /// Emit MIR for this item body. - pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> { - self.body() - .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))? - .dump(w, &self.name()) - } -} - -/// Return the function where execution starts if the current -/// crate defines that. This is usually `main`, but could be -/// `start` if the crate is a no-std crate. -pub fn entry_fn() -> Option<CrateItem> { - with(|cx| cx.entry_fn()) -} - -/// Access to the local crate. -pub fn local_crate() -> Crate { - with(|cx| cx.local_crate()) -} - -/// Try to find a crate or crates if multiple crates exist from given name. -pub fn find_crates(name: &str) -> Vec<Crate> { - with(|cx| cx.find_crates(name)) -} - -/// Try to find a crate with the given name. -pub fn external_crates() -> Vec<Crate> { - with(|cx| cx.external_crates()) -} - -/// Retrieve all items in the local crate that have a MIR associated with them. -pub fn all_local_items() -> CrateItems { - with(|cx| cx.all_local_items()) -} - -pub fn all_trait_decls() -> TraitDecls { - with(|cx| cx.all_trait_decls()) -} - -pub fn all_trait_impls() -> ImplTraitDecls { - with(|cx| cx.all_trait_impls()) -} - -/// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone, PartialEq, Eq, Hash, Serialize)] -pub struct Opaque(String); - -impl std::fmt::Display for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -pub fn opaque<T: Debug>(value: &T) -> Opaque { - Opaque(format!("{value:?}")) -} - -macro_rules! bridge_impl { - ($name: ident, $ty: ty) => { - impl rustc_smir::bridge::$name<compiler_interface::BridgeTys> for $ty { - fn new(def: stable_mir::DefId) -> Self { - Self(def) - } - } - }; -} - -bridge_impl!(CrateItem, stable_mir::CrateItem); -bridge_impl!(AdtDef, stable_mir::ty::AdtDef); -bridge_impl!(ForeignModuleDef, stable_mir::ty::ForeignModuleDef); -bridge_impl!(ForeignDef, stable_mir::ty::ForeignDef); -bridge_impl!(FnDef, stable_mir::ty::FnDef); -bridge_impl!(ClosureDef, stable_mir::ty::ClosureDef); -bridge_impl!(CoroutineDef, stable_mir::ty::CoroutineDef); -bridge_impl!(CoroutineClosureDef, stable_mir::ty::CoroutineClosureDef); -bridge_impl!(AliasDef, stable_mir::ty::AliasDef); -bridge_impl!(ParamDef, stable_mir::ty::ParamDef); -bridge_impl!(BrNamedDef, stable_mir::ty::BrNamedDef); -bridge_impl!(TraitDef, stable_mir::ty::TraitDef); -bridge_impl!(GenericDef, stable_mir::ty::GenericDef); -bridge_impl!(ConstDef, stable_mir::ty::ConstDef); -bridge_impl!(ImplDef, stable_mir::ty::ImplDef); -bridge_impl!(RegionDef, stable_mir::ty::RegionDef); -bridge_impl!(CoroutineWitnessDef, stable_mir::ty::CoroutineWitnessDef); -bridge_impl!(AssocDef, stable_mir::ty::AssocDef); -bridge_impl!(OpaqueDef, stable_mir::ty::OpaqueDef); -bridge_impl!(StaticDef, stable_mir::mir::mono::StaticDef); - -impl rustc_smir::bridge::Prov<compiler_interface::BridgeTys> for stable_mir::ty::Prov { - fn new(aid: stable_mir::mir::alloc::AllocId) -> Self { - Self(aid) - } -} - -impl rustc_smir::bridge::Allocation<compiler_interface::BridgeTys> for stable_mir::ty::Allocation { - fn new<'tcx>( - bytes: Vec<Option<u8>>, - ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>, - align: u64, - mutability: rustc_middle::mir::Mutability, - tables: &mut Tables<'tcx, compiler_interface::BridgeTys>, - cx: &SmirCtxt<'tcx, compiler_interface::BridgeTys>, - ) -> Self { - Self { - bytes, - provenance: ProvenanceMap { - ptrs: ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect(), - }, - align, - mutability: mutability.stable(tables, cx), - } - } -} diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index c779720f97b..27b41cc09ed 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -334,7 +334,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let xlen = cx.data_layout().pointer_size.bits(); + let xlen = cx.data_layout().pointer_size().bits(); let flen = match &cx.target_spec().llvm_abiname[..] { "ilp32f" | "lp64f" => 32, "ilp32d" | "lp64d" => 64, @@ -369,7 +369,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let grlen = cx.data_layout().pointer_size.bits(); + let grlen = cx.data_layout().pointer_size().bits(); for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { diff --git a/compiler/rustc_target/src/callconv/mips.rs b/compiler/rustc_target/src/callconv/mips.rs index 6162267a0d0..48a01da865b 100644 --- a/compiler/rustc_target/src/callconv/mips.rs +++ b/compiler/rustc_target/src/callconv/mips.rs @@ -10,7 +10,7 @@ where ret.extend_integer_width_to(32); } else { ret.make_indirect(); - *offset += cx.data_layout().pointer_size; + *offset += cx.data_layout().pointer_size(); } } diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 71cc2a45563..ab3271220eb 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -733,7 +733,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } if arg_idx.is_none() - && arg.layout.size > Primitive::Pointer(AddressSpace::DATA).size(cx) * 2 + && arg.layout.size > Primitive::Pointer(AddressSpace::ZERO).size(cx) * 2 && !matches!(arg.layout.backend_repr, BackendRepr::SimdVector { .. }) { // Return values larger than 2 registers using a return area @@ -792,7 +792,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { let size = arg.layout.size; if arg.layout.is_sized() - && size <= Primitive::Pointer(AddressSpace::DATA).size(cx) + && size <= Primitive::Pointer(AddressSpace::ZERO).size(cx) { // We want to pass small aggregates as immediates, but using // an LLVM aggregate type for this leads to bad optimizations, diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 6a2038f9381..a06f54d60e7 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -418,7 +418,7 @@ where "ilp32d" | "lp64d" => 64, _ => 0, }; - let xlen = cx.data_layout().pointer_size.bits(); + let xlen = cx.data_layout().pointer_size().bits(); let mut avail_gprs = 8; let mut avail_fprs = 8; @@ -448,7 +448,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - let xlen = cx.data_layout().pointer_size.bits(); + let xlen = cx.data_layout().pointer_size().bits(); for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { diff --git a/compiler/rustc_target/src/callconv/sparc.rs b/compiler/rustc_target/src/callconv/sparc.rs index 6162267a0d0..48a01da865b 100644 --- a/compiler/rustc_target/src/callconv/sparc.rs +++ b/compiler/rustc_target/src/callconv/sparc.rs @@ -10,7 +10,7 @@ where ret.extend_integer_width_to(32); } else { ret.make_indirect(); - *offset += cx.data_layout().pointer_size; + *offset += cx.data_layout().pointer_size(); } } diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index bdf116ff303..918b71c80c4 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -219,7 +219,7 @@ where // SSE ABI. We prefer this over integer registers as float scalars need to be in SSE // registers for float operations, so that's the best place to pass them around. fn_abi.ret.cast_to(Reg { kind: RegKind::Vector, size: fn_abi.ret.layout.size }); - } else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) { + } else if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::ZERO).size(cx) { // Same size or smaller than pointer, return in an integer register. fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size }); } else { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 7a49f004072..5346b206a17 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2198,7 +2198,10 @@ pub struct TargetMetadata { impl Target { pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> { - let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?; + let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string( + &self.data_layout, + self.options.default_address_space, + )?; // Perform consistency checks against the Target information. if dl.endian != self.endian { @@ -2209,9 +2212,10 @@ impl Target { } let target_pointer_width: u64 = self.pointer_width.into(); - if dl.pointer_size.bits() != target_pointer_width { + let dl_pointer_size: u64 = dl.pointer_size().bits(); + if dl_pointer_size != target_pointer_width { return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth { - pointer_size: dl.pointer_size.bits(), + pointer_size: dl_pointer_size, target: self.pointer_width, }); } @@ -2650,6 +2654,11 @@ pub struct TargetOptions { /// Whether the target supports XRay instrumentation. pub supports_xray: bool, + /// The default address space for this target. When using LLVM as a backend, most targets simply + /// use LLVM's default address space (0). Some other targets, such as CHERI targets, use a + /// custom default address space (in this specific case, `200`). + pub default_address_space: rustc_abi::AddressSpace, + /// Whether the targets supports -Z small-data-threshold small_data_threshold_support: SmallDataThresholdSupport, } @@ -2878,6 +2887,7 @@ impl Default for TargetOptions { entry_name: "main".into(), entry_abi: CanonAbi::C, supports_xray: false, + default_address_space: rustc_abi::AddressSpace::ZERO, small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch, } } diff --git a/compiler/rustc_thread_pool/Cargo.toml b/compiler/rustc_thread_pool/Cargo.toml index d0bd065c457..b0194834264 100644 --- a/compiler/rustc_thread_pool/Cargo.toml +++ b/compiler/rustc_thread_pool/Cargo.toml @@ -1,8 +1,10 @@ [package] name = "rustc_thread_pool" version = "0.0.0" -authors = ["Niko Matsakis <niko@alum.mit.edu>", - "Josh Stone <cuviper@gmail.com>"] +authors = [ + "Niko Matsakis <niko@alum.mit.edu>", + "Josh Stone <cuviper@gmail.com>", +] description = "Core APIs for Rayon - fork for rustc" license = "MIT OR Apache-2.0" rust-version = "1.63" @@ -14,6 +16,7 @@ categories = ["concurrency"] [dependencies] crossbeam-deque = "0.8" crossbeam-utils = "0.8" +smallvec = "1.8.1" [dev-dependencies] rand = "0.9" diff --git a/compiler/rustc_thread_pool/src/broadcast/mod.rs b/compiler/rustc_thread_pool/src/broadcast/mod.rs index 9545c4b15d8..1707ebb5988 100644 --- a/compiler/rustc_thread_pool/src/broadcast/mod.rs +++ b/compiler/rustc_thread_pool/src/broadcast/mod.rs @@ -1,6 +1,7 @@ use std::fmt; use std::marker::PhantomData; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use crate::job::{ArcJob, StackJob}; use crate::latch::{CountLatch, LatchRef}; @@ -97,13 +98,22 @@ where OP: Fn(BroadcastContext<'_>) -> R + Sync, R: Send, { + let current_thread = WorkerThread::current(); + let current_thread_addr = current_thread.expose_provenance(); + let started = &AtomicBool::new(false); let f = move |injected: bool| { debug_assert!(injected); + + // Mark as started if we are the thread that initiated that broadcast. + if current_thread_addr == WorkerThread::current().expose_provenance() { + started.store(true, Ordering::Relaxed); + } + BroadcastContext::with(&op) }; let n_threads = registry.num_threads(); - let current_thread = unsafe { WorkerThread::current().as_ref() }; + let current_thread = unsafe { current_thread.as_ref() }; let tlv = crate::tlv::get(); let latch = CountLatch::with_count(n_threads, current_thread); let jobs: Vec<_> = @@ -112,8 +122,16 @@ where registry.inject_broadcast(job_refs); + let current_thread_job_id = current_thread + .and_then(|worker| (registry.id() == worker.registry.id()).then(|| worker)) + .map(|worker| unsafe { jobs[worker.index()].as_job_ref() }.id()); + // Wait for all jobs to complete, then collect the results, maybe propagating a panic. - latch.wait(current_thread); + latch.wait( + current_thread, + || started.load(Ordering::Relaxed), + |job| Some(job.id()) == current_thread_job_id, + ); jobs.into_iter().map(|job| unsafe { job.into_result() }).collect() } @@ -129,7 +147,7 @@ where { let job = ArcJob::new({ let registry = Arc::clone(registry); - move || { + move |_| { registry.catch_unwind(|| BroadcastContext::with(&op)); registry.terminate(); // (*) permit registry to terminate now } diff --git a/compiler/rustc_thread_pool/src/broadcast/tests.rs b/compiler/rustc_thread_pool/src/broadcast/tests.rs index fac8b8ad466..2fe1319726c 100644 --- a/compiler/rustc_thread_pool/src/broadcast/tests.rs +++ b/compiler/rustc_thread_pool/src/broadcast/tests.rs @@ -64,7 +64,9 @@ fn spawn_broadcast_self() { assert!(v.into_iter().eq(0..7)); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn broadcast_mutual() { let count = AtomicUsize::new(0); @@ -98,7 +100,9 @@ fn spawn_broadcast_mutual() { assert_eq!(rx.into_iter().count(), 3 * 7); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn broadcast_mutual_sleepy() { let count = AtomicUsize::new(0); diff --git a/compiler/rustc_thread_pool/src/job.rs b/compiler/rustc_thread_pool/src/job.rs index e6e84ac2320..60a64fe59c9 100644 --- a/compiler/rustc_thread_pool/src/job.rs +++ b/compiler/rustc_thread_pool/src/job.rs @@ -27,6 +27,11 @@ pub(super) trait Job { unsafe fn execute(this: *const ()); } +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub(super) struct JobRefId { + pointer: usize, +} + /// Effectively a Job trait object. Each JobRef **must** be executed /// exactly once, or else data may leak. /// @@ -52,11 +57,9 @@ impl JobRef { JobRef { pointer: data as *const (), execute_fn: <T as Job>::execute } } - /// Returns an opaque handle that can be saved and compared, - /// without making `JobRef` itself `Copy + Eq`. #[inline] - pub(super) fn id(&self) -> impl Eq { - (self.pointer, self.execute_fn) + pub(super) fn id(&self) -> JobRefId { + JobRefId { pointer: self.pointer.expose_provenance() } } #[inline] @@ -100,8 +103,15 @@ where unsafe { JobRef::new(self) } } - pub(super) unsafe fn run_inline(self, stolen: bool) -> R { - self.func.into_inner().unwrap()(stolen) + pub(super) unsafe fn run_inline(&self, stolen: bool) { + unsafe { + let func = (*self.func.get()).take().unwrap(); + *(self.result.get()) = match unwind::halt_unwinding(|| func(stolen)) { + Ok(x) => JobResult::Ok(x), + Err(x) => JobResult::Panic(x), + }; + Latch::set(&self.latch); + } } pub(super) unsafe fn into_result(self) -> R { @@ -138,7 +148,7 @@ where /// (Probably `StackJob` should be refactored in a similar fashion.) pub(super) struct HeapJob<BODY> where - BODY: FnOnce() + Send, + BODY: FnOnce(JobRefId) + Send, { job: BODY, tlv: Tlv, @@ -146,7 +156,7 @@ where impl<BODY> HeapJob<BODY> where - BODY: FnOnce() + Send, + BODY: FnOnce(JobRefId) + Send, { pub(super) fn new(tlv: Tlv, job: BODY) -> Box<Self> { Box::new(HeapJob { job, tlv }) @@ -170,12 +180,13 @@ where impl<BODY> Job for HeapJob<BODY> where - BODY: FnOnce() + Send, + BODY: FnOnce(JobRefId) + Send, { unsafe fn execute(this: *const ()) { + let pointer = this.expose_provenance(); let this = unsafe { Box::from_raw(this as *mut Self) }; tlv::set(this.tlv); - (this.job)(); + (this.job)(JobRefId { pointer }); } } @@ -183,14 +194,14 @@ where /// be turned into multiple `JobRef`s and called multiple times. pub(super) struct ArcJob<BODY> where - BODY: Fn() + Send + Sync, + BODY: Fn(JobRefId) + Send + Sync, { job: BODY, } impl<BODY> ArcJob<BODY> where - BODY: Fn() + Send + Sync, + BODY: Fn(JobRefId) + Send + Sync, { pub(super) fn new(job: BODY) -> Arc<Self> { Arc::new(ArcJob { job }) @@ -214,11 +225,12 @@ where impl<BODY> Job for ArcJob<BODY> where - BODY: Fn() + Send + Sync, + BODY: Fn(JobRefId) + Send + Sync, { unsafe fn execute(this: *const ()) { + let pointer = this.expose_provenance(); let this = unsafe { Arc::from_raw(this as *mut Self) }; - (this.job)(); + (this.job)(JobRefId { pointer }); } } diff --git a/compiler/rustc_thread_pool/src/join/mod.rs b/compiler/rustc_thread_pool/src/join/mod.rs index f285362c19b..08c4c4e96ab 100644 --- a/compiler/rustc_thread_pool/src/join/mod.rs +++ b/compiler/rustc_thread_pool/src/join/mod.rs @@ -1,10 +1,8 @@ -use std::any::Any; +use std::sync::atomic::{AtomicBool, Ordering}; use crate::job::StackJob; use crate::latch::SpinLatch; -use crate::registry::{self, WorkerThread}; -use crate::tlv::{self, Tlv}; -use crate::{FnContext, unwind}; +use crate::{FnContext, registry, tlv, unwind}; #[cfg(test)] mod tests; @@ -134,68 +132,38 @@ where // Create virtual wrapper for task b; this all has to be // done here so that the stack frame can keep it all live // long enough. - let job_b = StackJob::new(tlv, call_b(oper_b), SpinLatch::new(worker_thread)); + let job_b_started = AtomicBool::new(false); + let job_b = StackJob::new( + tlv, + |migrated| { + job_b_started.store(true, Ordering::Relaxed); + call_b(oper_b)(migrated) + }, + SpinLatch::new(worker_thread), + ); let job_b_ref = job_b.as_job_ref(); let job_b_id = job_b_ref.id(); worker_thread.push(job_b_ref); // Execute task a; hopefully b gets stolen in the meantime. let status_a = unwind::halt_unwinding(call_a(oper_a, injected)); - let result_a = match status_a { - Ok(v) => v, - Err(err) => join_recover_from_panic(worker_thread, &job_b.latch, err, tlv), - }; - - // Now that task A has finished, try to pop job B from the - // local stack. It may already have been popped by job A; it - // may also have been stolen. There may also be some tasks - // pushed on top of it in the stack, and we will have to pop - // those off to get to it. - while !job_b.latch.probe() { - if let Some(job) = worker_thread.take_local_job() { - if job_b_id == job.id() { - // Found it! Let's run it. - // - // Note that this could panic, but it's ok if we unwind here. - - // Restore the TLV since we might have run some jobs overwriting it when waiting for job b. - tlv::set(tlv); - - let result_b = job_b.run_inline(injected); - return (result_a, result_b); - } else { - worker_thread.execute(job); - } - } else { - // Local deque is empty. Time to steal from other - // threads. - worker_thread.wait_until(&job_b.latch); - debug_assert!(job_b.latch.probe()); - break; - } - } + worker_thread.wait_for_jobs::<_, false>( + &job_b.latch, + || job_b_started.load(Ordering::Relaxed), + |job| job.id() == job_b_id, + |job| { + debug_assert_eq!(job.id(), job_b_id); + job_b.run_inline(injected); + }, + ); // Restore the TLV since we might have run some jobs overwriting it when waiting for job b. tlv::set(tlv); + let result_a = match status_a { + Ok(v) => v, + Err(err) => unwind::resume_unwinding(err), + }; (result_a, job_b.into_result()) }) } - -/// If job A panics, we still cannot return until we are sure that job -/// B is complete. This is because it may contain references into the -/// enclosing stack frame(s). -#[cold] // cold path -unsafe fn join_recover_from_panic( - worker_thread: &WorkerThread, - job_b_latch: &SpinLatch<'_>, - err: Box<dyn Any + Send>, - tlv: Tlv, -) -> ! { - unsafe { worker_thread.wait_until(job_b_latch) }; - - // Restore the TLV since we might have run some jobs overwriting it when waiting for job b. - tlv::set(tlv); - - unwind::resume_unwinding(err) -} diff --git a/compiler/rustc_thread_pool/src/join/tests.rs b/compiler/rustc_thread_pool/src/join/tests.rs index 9df99072c3a..71a971435bc 100644 --- a/compiler/rustc_thread_pool/src/join/tests.rs +++ b/compiler/rustc_thread_pool/src/join/tests.rs @@ -96,7 +96,9 @@ fn join_context_both() { assert!(b_migrated); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn join_context_neither() { // If we're already in a 1-thread pool, neither job should be stolen. diff --git a/compiler/rustc_thread_pool/src/latch.rs b/compiler/rustc_thread_pool/src/latch.rs index 49ba62d3bea..18d654d9f78 100644 --- a/compiler/rustc_thread_pool/src/latch.rs +++ b/compiler/rustc_thread_pool/src/latch.rs @@ -3,6 +3,7 @@ use std::ops::Deref; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Condvar, Mutex}; +use crate::job::JobRef; use crate::registry::{Registry, WorkerThread}; /// We define various kinds of latches, which are all a primitive signaling @@ -166,11 +167,6 @@ impl<'r> SpinLatch<'r> { pub(super) fn cross(thread: &'r WorkerThread) -> SpinLatch<'r> { SpinLatch { cross: true, ..SpinLatch::new(thread) } } - - #[inline] - pub(super) fn probe(&self) -> bool { - self.core_latch.probe() - } } impl<'r> AsCoreLatch for SpinLatch<'r> { @@ -368,13 +364,20 @@ impl CountLatch { debug_assert!(old_counter != 0); } - pub(super) fn wait(&self, owner: Option<&WorkerThread>) { + pub(super) fn wait( + &self, + owner: Option<&WorkerThread>, + all_jobs_started: impl FnMut() -> bool, + is_job: impl FnMut(&JobRef) -> bool, + ) { match &self.kind { CountLatchKind::Stealing { latch, registry, worker_index } => unsafe { let owner = owner.expect("owner thread"); debug_assert_eq!(registry.id(), owner.registry().id()); debug_assert_eq!(*worker_index, owner.index()); - owner.wait_until(latch); + owner.wait_for_jobs::<_, true>(latch, all_jobs_started, is_job, |job| { + owner.execute(job); + }); }, CountLatchKind::Blocking { latch } => latch.wait(), } diff --git a/compiler/rustc_thread_pool/src/registry.rs b/compiler/rustc_thread_pool/src/registry.rs index 03a01aa29d2..22d3a786045 100644 --- a/compiler/rustc_thread_pool/src/registry.rs +++ b/compiler/rustc_thread_pool/src/registry.rs @@ -6,6 +6,7 @@ use std::sync::{Arc, Mutex, Once}; use std::{fmt, io, mem, ptr, thread}; use crossbeam_deque::{Injector, Steal, Stealer, Worker}; +use smallvec::SmallVec; use crate::job::{JobFifo, JobRef, StackJob}; use crate::latch::{AsCoreLatch, CoreLatch, Latch, LatchRef, LockLatch, OnceLatch, SpinLatch}; @@ -796,14 +797,83 @@ impl WorkerThread { /// stealing tasks as necessary. #[inline] pub(super) unsafe fn wait_until<L: AsCoreLatch + ?Sized>(&self, latch: &L) { + unsafe { self.wait_or_steal_until(latch, false) }; + } + + /// Wait until the latch is set. Executes local jobs if `is_job` is true for them and + /// `all_jobs_started` still returns false. + #[inline] + pub(super) unsafe fn wait_for_jobs<L: AsCoreLatch + ?Sized, const BROADCAST_JOBS: bool>( + &self, + latch: &L, + mut all_jobs_started: impl FnMut() -> bool, + mut is_job: impl FnMut(&JobRef) -> bool, + mut execute_job: impl FnMut(JobRef) -> (), + ) { + let mut jobs = SmallVec::<[JobRef; 8]>::new(); + let mut broadcast_jobs = SmallVec::<[JobRef; 8]>::new(); + + while !all_jobs_started() { + if let Some(job) = self.worker.pop() { + if is_job(&job) { + execute_job(job); + } else { + jobs.push(job); + } + } else { + if BROADCAST_JOBS { + let broadcast_job = loop { + match self.stealer.steal() { + Steal::Success(job) => break Some(job), + Steal::Empty => break None, + Steal::Retry => continue, + } + }; + if let Some(job) = broadcast_job { + if is_job(&job) { + execute_job(job); + } else { + broadcast_jobs.push(job); + } + } + } + break; + } + } + + // Restore the jobs that we weren't looking for. + for job in jobs { + self.worker.push(job); + } + if BROADCAST_JOBS { + let broadcasts = self.registry.broadcasts.lock().unwrap(); + for job in broadcast_jobs { + broadcasts[self.index].push(job); + } + } + + // Wait for the jobs to finish. + unsafe { self.wait_until(latch) }; + debug_assert!(latch.as_core_latch().probe()); + } + + pub(super) unsafe fn wait_or_steal_until<L: AsCoreLatch + ?Sized>( + &self, + latch: &L, + steal: bool, + ) { let latch = latch.as_core_latch(); if !latch.probe() { - unsafe { self.wait_until_cold(latch) }; + if steal { + unsafe { self.wait_or_steal_until_cold(latch) }; + } else { + unsafe { self.wait_until_cold(latch) }; + } } } #[cold] - unsafe fn wait_until_cold(&self, latch: &CoreLatch) { + unsafe fn wait_or_steal_until_cold(&self, latch: &CoreLatch) { // the code below should swallow all panics and hence never // unwind; but if something does wrong, we want to abort, // because otherwise other code in rayon may assume that the @@ -827,7 +897,7 @@ impl WorkerThread { // The job might have injected local work, so go back to the outer loop. continue 'outer; } else { - self.registry.sleep.no_work_found(&mut idle_state, latch, &self) + self.registry.sleep.no_work_found(&mut idle_state, latch, &self, true) } } @@ -840,13 +910,34 @@ impl WorkerThread { mem::forget(abort_guard); // successful execution, do not abort } + #[cold] + unsafe fn wait_until_cold(&self, latch: &CoreLatch) { + // the code below should swallow all panics and hence never + // unwind; but if something does wrong, we want to abort, + // because otherwise other code in rayon may assume that the + // latch has been signaled, and that can lead to random memory + // accesses, which would be *very bad* + let abort_guard = unwind::AbortIfPanic; + + let mut idle_state = self.registry.sleep.start_looking(self.index); + while !latch.probe() { + self.registry.sleep.no_work_found(&mut idle_state, latch, &self, false); + } + + // If we were sleepy, we are not anymore. We "found work" -- + // whatever the surrounding thread was doing before it had to wait. + self.registry.sleep.work_found(); + + mem::forget(abort_guard); // successful execution, do not abort + } + unsafe fn wait_until_out_of_work(&self) { debug_assert_eq!(self as *const _, WorkerThread::current()); let registry = &*self.registry; let index = self.index; registry.acquire_thread(); - unsafe { self.wait_until(®istry.thread_infos[index].terminate) }; + unsafe { self.wait_or_steal_until(®istry.thread_infos[index].terminate, true) }; // Should not be any work left in our queue. debug_assert!(self.take_local_job().is_none()); diff --git a/compiler/rustc_thread_pool/src/scope/mod.rs b/compiler/rustc_thread_pool/src/scope/mod.rs index 55e58b3509d..38230383965 100644 --- a/compiler/rustc_thread_pool/src/scope/mod.rs +++ b/compiler/rustc_thread_pool/src/scope/mod.rs @@ -6,14 +6,15 @@ //! [`join()`]: ../join/join.fn.html use std::any::Any; +use std::collections::HashSet; use std::marker::PhantomData; use std::mem::ManuallyDrop; -use std::sync::Arc; use std::sync::atomic::{AtomicPtr, Ordering}; +use std::sync::{Arc, Mutex}; use std::{fmt, ptr}; use crate::broadcast::BroadcastContext; -use crate::job::{ArcJob, HeapJob, JobFifo, JobRef}; +use crate::job::{ArcJob, HeapJob, JobFifo, JobRef, JobRefId}; use crate::latch::{CountLatch, Latch}; use crate::registry::{Registry, WorkerThread, global_registry, in_worker}; use crate::tlv::{self, Tlv}; @@ -52,6 +53,13 @@ struct ScopeBase<'scope> { /// latch to track job counts job_completed_latch: CountLatch, + /// Jobs that have been spawned, but not yet started. + #[allow(rustc::default_hash_types)] + pending_jobs: Mutex<HashSet<JobRefId>>, + + /// The worker which will wait on scope completion, if any. + worker: Option<usize>, + /// You can think of a scope as containing a list of closures to execute, /// all of which outlive `'scope`. They're not actually required to be /// `Sync`, but it's still safe to let the `Scope` implement `Sync` because @@ -525,13 +533,19 @@ impl<'scope> Scope<'scope> { BODY: FnOnce(&Scope<'scope>) + Send + 'scope, { let scope_ptr = ScopePtr(self); - let job = HeapJob::new(self.base.tlv, move || unsafe { + let job = HeapJob::new(self.base.tlv, move |id| unsafe { // SAFETY: this job will execute before the scope ends. let scope = scope_ptr.as_ref(); + + // Mark this job is started. + scope.base.pending_jobs.lock().unwrap().remove(&id); + ScopeBase::execute_job(&scope.base, move || body(scope)) }); let job_ref = self.base.heap_job_ref(job); + // Mark this job as pending. + self.base.pending_jobs.lock().unwrap().insert(job_ref.id()); // Since `Scope` implements `Sync`, we can't be sure that we're still in a // thread of this pool, so we can't just push to the local worker thread. // Also, this might be an in-place scope. @@ -547,10 +561,17 @@ impl<'scope> Scope<'scope> { BODY: Fn(&Scope<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope, { let scope_ptr = ScopePtr(self); - let job = ArcJob::new(move || unsafe { + let job = ArcJob::new(move |id| unsafe { // SAFETY: this job will execute before the scope ends. let scope = scope_ptr.as_ref(); let body = &body; + + let current_index = WorkerThread::current().as_ref().map(|worker| worker.index()); + if current_index == scope.base.worker { + // Mark this job as started on the scope's worker thread. + scope.base.pending_jobs.lock().unwrap().remove(&id); + } + let func = move || BroadcastContext::with(move |ctx| body(scope, ctx)); ScopeBase::execute_job(&scope.base, func) }); @@ -585,23 +606,24 @@ impl<'scope> ScopeFifo<'scope> { BODY: FnOnce(&ScopeFifo<'scope>) + Send + 'scope, { let scope_ptr = ScopePtr(self); - let job = HeapJob::new(self.base.tlv, move || unsafe { + let job = HeapJob::new(self.base.tlv, move |id| unsafe { // SAFETY: this job will execute before the scope ends. let scope = scope_ptr.as_ref(); + + // Mark this job is started. + scope.base.pending_jobs.lock().unwrap().remove(&id); + ScopeBase::execute_job(&scope.base, move || body(scope)) }); let job_ref = self.base.heap_job_ref(job); - // If we're in the pool, use our scope's private fifo for this thread to execute - // in a locally-FIFO order. Otherwise, just use the pool's global injector. - match self.base.registry.current_thread() { - Some(worker) => { - let fifo = &self.fifos[worker.index()]; - // SAFETY: this job will execute before the scope ends. - unsafe { worker.push(fifo.push(job_ref)) }; - } - None => self.base.registry.inject(job_ref), - } + // Mark this job as pending. + self.base.pending_jobs.lock().unwrap().insert(job_ref.id()); + + // Since `ScopeFifo` implements `Sync`, we can't be sure that we're still in a + // thread of this pool, so we can't just push to the local worker thread. + // Also, this might be an in-place scope. + self.base.registry.inject_or_push(job_ref); } /// Spawns a job into every thread of the fork-join scope `self`. This job will @@ -613,9 +635,15 @@ impl<'scope> ScopeFifo<'scope> { BODY: Fn(&ScopeFifo<'scope>, BroadcastContext<'_>) + Send + Sync + 'scope, { let scope_ptr = ScopePtr(self); - let job = ArcJob::new(move || unsafe { + let job = ArcJob::new(move |id| unsafe { // SAFETY: this job will execute before the scope ends. let scope = scope_ptr.as_ref(); + + let current_index = WorkerThread::current().as_ref().map(|worker| worker.index()); + if current_index == scope.base.worker { + // Mark this job as started on the scope's worker thread. + scope.base.pending_jobs.lock().unwrap().remove(&id); + } let body = &body; let func = move || BroadcastContext::with(move |ctx| body(scope, ctx)); ScopeBase::execute_job(&scope.base, func) @@ -636,6 +664,9 @@ impl<'scope> ScopeBase<'scope> { registry: Arc::clone(registry), panic: AtomicPtr::new(ptr::null_mut()), job_completed_latch: CountLatch::new(owner), + #[allow(rustc::default_hash_types)] + pending_jobs: Mutex::new(HashSet::new()), + worker: owner.map(|w| w.index()), marker: PhantomData, tlv: tlv::get(), } @@ -643,7 +674,7 @@ impl<'scope> ScopeBase<'scope> { fn heap_job_ref<FUNC>(&self, job: Box<HeapJob<FUNC>>) -> JobRef where - FUNC: FnOnce() + Send + 'scope, + FUNC: FnOnce(JobRefId) + Send + 'scope, { unsafe { self.job_completed_latch.increment(); @@ -653,8 +684,12 @@ impl<'scope> ScopeBase<'scope> { fn inject_broadcast<FUNC>(&self, job: Arc<ArcJob<FUNC>>) where - FUNC: Fn() + Send + Sync + 'scope, + FUNC: Fn(JobRefId) + Send + Sync + 'scope, { + if self.worker.is_some() { + let id = unsafe { ArcJob::as_job_ref(&job).id() }; + self.pending_jobs.lock().unwrap().insert(id); + } let n_threads = self.registry.num_threads(); let job_refs = (0..n_threads).map(|_| unsafe { self.job_completed_latch.increment(); @@ -671,7 +706,11 @@ impl<'scope> ScopeBase<'scope> { FUNC: FnOnce() -> R, { let result = unsafe { Self::execute_job_closure(self, func) }; - self.job_completed_latch.wait(owner); + self.job_completed_latch.wait( + owner, + || self.pending_jobs.lock().unwrap().is_empty(), + |job| self.pending_jobs.lock().unwrap().contains(&job.id()), + ); // Restore the TLV if we ran some jobs while waiting tlv::set(self.tlv); diff --git a/compiler/rustc_thread_pool/src/scope/tests.rs b/compiler/rustc_thread_pool/src/scope/tests.rs index 2df3bc67e29..9b9ac98d066 100644 --- a/compiler/rustc_thread_pool/src/scope/tests.rs +++ b/compiler/rustc_thread_pool/src/scope/tests.rs @@ -289,7 +289,9 @@ macro_rules! test_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn lifo_order() { // In the absence of stealing, `scope()` runs its `spawn()` jobs in LIFO order. @@ -298,7 +300,9 @@ fn lifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn fifo_order() { // In the absence of stealing, `scope_fifo()` runs its `spawn_fifo()` jobs in FIFO order. @@ -333,7 +337,9 @@ macro_rules! test_nested_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_lifo_order() { // In the absence of stealing, `scope()` runs its `spawn()` jobs in LIFO order. @@ -342,7 +348,9 @@ fn nested_lifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_fifo_order() { // In the absence of stealing, `scope_fifo()` runs its `spawn_fifo()` jobs in FIFO order. @@ -351,7 +359,9 @@ fn nested_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_lifo_fifo_order() { // LIFO on the outside, FIFO on the inside @@ -360,7 +370,9 @@ fn nested_lifo_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_fifo_lifo_order() { // FIFO on the outside, LIFO on the inside @@ -401,7 +413,9 @@ macro_rules! test_mixed_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_lifo_order() { // NB: the end of the inner scope makes us execute some of the outer scope @@ -411,7 +425,9 @@ fn mixed_lifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_fifo_order() { let vec = test_mixed_order!(scope_fifo => spawn_fifo, scope_fifo => spawn_fifo); @@ -419,7 +435,9 @@ fn mixed_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_lifo_fifo_order() { // NB: the end of the inner scope makes us execute some of the outer scope @@ -429,7 +447,9 @@ fn mixed_lifo_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_fifo_lifo_order() { let vec = test_mixed_order!(scope_fifo => spawn_fifo, scope => spawn); @@ -519,8 +539,9 @@ fn mixed_lifetime_scope_fifo() { #[test] fn scope_spawn_broadcast() { + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); let sum = AtomicUsize::new(0); - let n = scope(|s| { + let n = pool.scope(|s| { s.spawn_broadcast(|_, ctx| { sum.fetch_add(ctx.index(), Ordering::Relaxed); }); @@ -531,8 +552,9 @@ fn scope_spawn_broadcast() { #[test] fn scope_fifo_spawn_broadcast() { + let pool = ThreadPoolBuilder::new().num_threads(7).build().unwrap(); let sum = AtomicUsize::new(0); - let n = scope_fifo(|s| { + let n = pool.scope_fifo(|s| { s.spawn_broadcast(|_, ctx| { sum.fetch_add(ctx.index(), Ordering::Relaxed); }); @@ -541,7 +563,9 @@ fn scope_fifo_spawn_broadcast() { assert_eq!(sum.into_inner(), n * (n - 1) / 2); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] fn scope_spawn_broadcast_nested() { let sum = AtomicUsize::new(0); let n = scope(|s| { diff --git a/compiler/rustc_thread_pool/src/sleep/mod.rs b/compiler/rustc_thread_pool/src/sleep/mod.rs index a9cdf68cc7e..31bf7184b42 100644 --- a/compiler/rustc_thread_pool/src/sleep/mod.rs +++ b/compiler/rustc_thread_pool/src/sleep/mod.rs @@ -144,6 +144,7 @@ impl Sleep { idle_state: &mut IdleState, latch: &CoreLatch, thread: &WorkerThread, + steal: bool, ) { if idle_state.rounds < ROUNDS_UNTIL_SLEEPY { thread::yield_now(); @@ -157,7 +158,7 @@ impl Sleep { thread::yield_now(); } else { debug_assert_eq!(idle_state.rounds, ROUNDS_UNTIL_SLEEPING); - self.sleep(idle_state, latch, thread); + self.sleep(idle_state, latch, thread, steal); } } @@ -167,7 +168,13 @@ impl Sleep { } #[cold] - fn sleep(&self, idle_state: &mut IdleState, latch: &CoreLatch, thread: &WorkerThread) { + fn sleep( + &self, + idle_state: &mut IdleState, + latch: &CoreLatch, + thread: &WorkerThread, + steal: bool, + ) { let worker_index = idle_state.worker_index; if !latch.get_sleepy() { @@ -215,7 +222,7 @@ impl Sleep { // - that job triggers the rollover over the JEC such that we don't see it // - we are the last active worker thread std::sync::atomic::fence(Ordering::SeqCst); - if thread.has_injected_job() { + if steal && thread.has_injected_job() { // If we see an externally injected job, then we have to 'wake // ourselves up'. (Ordinarily, `sub_sleeping_thread` is invoked by // the one that wakes us.) diff --git a/compiler/rustc_thread_pool/src/spawn/mod.rs b/compiler/rustc_thread_pool/src/spawn/mod.rs index 040a02bfa67..d403deaa108 100644 --- a/compiler/rustc_thread_pool/src/spawn/mod.rs +++ b/compiler/rustc_thread_pool/src/spawn/mod.rs @@ -95,7 +95,7 @@ where HeapJob::new(Tlv::null(), { let registry = Arc::clone(registry); - move || { + move |_| { registry.catch_unwind(func); registry.terminate(); // (*) permit registry to terminate now } diff --git a/compiler/rustc_thread_pool/src/spawn/tests.rs b/compiler/rustc_thread_pool/src/spawn/tests.rs index 8a70d2faf9c..119cfc7ca5e 100644 --- a/compiler/rustc_thread_pool/src/spawn/tests.rs +++ b/compiler/rustc_thread_pool/src/spawn/tests.rs @@ -166,7 +166,9 @@ macro_rules! test_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn lifo_order() { // In the absence of stealing, `spawn()` jobs on a thread will run in LIFO order. @@ -175,7 +177,9 @@ fn lifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn fifo_order() { // In the absence of stealing, `spawn_fifo()` jobs on a thread will run in FIFO order. @@ -184,7 +188,9 @@ fn fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn lifo_fifo_order() { // LIFO on the outside, FIFO on the inside @@ -193,7 +199,9 @@ fn lifo_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn fifo_lifo_order() { // FIFO on the outside, LIFO on the inside @@ -229,7 +237,9 @@ macro_rules! test_mixed_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_lifo_fifo_order() { let vec = test_mixed_order!(spawn, spawn_fifo); @@ -237,7 +247,9 @@ fn mixed_lifo_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mixed_fifo_lifo_order() { let vec = test_mixed_order!(spawn_fifo, spawn); diff --git a/compiler/rustc_thread_pool/src/thread_pool/tests.rs b/compiler/rustc_thread_pool/src/thread_pool/tests.rs index 42c99565088..f2baab4c859 100644 --- a/compiler/rustc_thread_pool/src/thread_pool/tests.rs +++ b/compiler/rustc_thread_pool/src/thread_pool/tests.rs @@ -151,7 +151,9 @@ fn self_install() { assert!(pool.install(|| pool.install(|| true))); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mutual_install() { let pool1 = ThreadPoolBuilder::new().num_threads(1).build().unwrap(); @@ -171,7 +173,9 @@ fn mutual_install() { assert!(ok); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn mutual_install_sleepy() { use std::{thread, time}; @@ -226,7 +230,9 @@ macro_rules! test_scope_order { }}; } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn scope_lifo_order() { let vec = test_scope_order!(scope => spawn); @@ -234,7 +240,9 @@ fn scope_lifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn scope_fifo_order() { let vec = test_scope_order!(scope_fifo => spawn_fifo); @@ -275,7 +283,9 @@ fn spawn_fifo_order() { assert_eq!(vec, expected); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_scopes() { // Create matching scopes for every thread pool. @@ -311,7 +321,9 @@ fn nested_scopes() { assert_eq!(counter.into_inner(), pools.len()); } +// FIXME: We should fix or remove this ignored test. #[test] +#[ignore] #[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] fn nested_fifo_scopes() { // Create matching fifo scopes for every thread pool. diff --git a/compiler/rustc_thread_pool/tests/stack_overflow_crash.rs b/compiler/rustc_thread_pool/tests/stack_overflow_crash.rs index 805b6d8ee3f..d854751542f 100644 --- a/compiler/rustc_thread_pool/tests/stack_overflow_crash.rs +++ b/compiler/rustc_thread_pool/tests/stack_overflow_crash.rs @@ -35,8 +35,9 @@ fn overflow_code() -> Option<i32> { ExitStatus::from_raw(0xc00000fd /*STATUS_STACK_OVERFLOW*/).code() } +// FIXME: We should fix or remove this test on Windows. #[test] -#[cfg_attr(not(any(unix, windows)), ignore)] +#[cfg_attr(not(any(unix)), ignore)] fn stack_overflow_crash() { // First check that the recursive call actually causes a stack overflow, // and does not get optimized away. diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 139b2997136..8fe4ffebd86 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -75,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { match arg.kind { - hir::TyKind::BareFn(_) => { + hir::TyKind::FnPtr(_) => { self.current_index.shift_in(1); let _ = intravisit::walk_ty(self, arg); self.current_index.shift_out(1); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 362052e9fdb..e801ec358fa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1187,6 +1187,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { has_custom_message: bool, ) -> bool { let span = obligation.cause.span; + let param_env = obligation.param_env; + + let mk_result = |trait_pred_and_new_ty| { + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty); + self.predicate_must_hold_modulo_regions(&obligation) + }; let code = match obligation.cause.code() { ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code, @@ -1195,6 +1202,76 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _) if self.tcx.hir_span(*hir_id).lo() == span.lo() => { + // `hir_id` corresponds to the HIR node that introduced a `where`-clause obligation. + // If that obligation comes from a type in an associated method call, we need + // special handling here. + if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id) + && let hir::ExprKind::Call(base, _) = expr.kind + && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) = base.kind + && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id) + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind + && ty.span == span + { + // We've encountered something like `&str::from("")`, where the intended code + // was likely `<&str>::from("")`. The former is interpreted as "call method + // `from` on `str` and borrow the result", while the latter means "call method + // `from` on `&str`". + + let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| { + (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) + }); + let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| { + (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) + }); + + let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); + let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); + let sugg_msg = |pre: &str| { + format!( + "you likely meant to call the associated function `{FN}` for type \ + `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \ + type `{TY}`", + FN = segment.ident, + TY = poly_trait_pred.self_ty(), + ) + }; + match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) { + (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => { + err.multipart_suggestion_verbose( + sugg_msg(mtbl.prefix_str()), + vec![ + (outer.span.shrink_to_lo(), "<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + (true, _, hir::Mutability::Mut) => { + // There's an associated function found on the immutable borrow of the + err.multipart_suggestion_verbose( + sugg_msg("mut "), + vec![ + (outer.span.shrink_to_lo().until(span), "<&".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + (_, true, hir::Mutability::Not) => { + err.multipart_suggestion_verbose( + sugg_msg(""), + vec![ + (outer.span.shrink_to_lo().until(span), "<&mut ".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + _ => {} + } + // If we didn't return early here, we would instead suggest `&&str::from("")`. + return false; + } c } c if matches!( @@ -1220,8 +1297,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { never_suggest_borrow.push(def_id); } - let param_env = obligation.param_env; - // Try to apply the original trait bound by borrowing. let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>, blacklist: &[DefId]| @@ -1243,11 +1318,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) }); - let mk_result = |trait_pred_and_new_ty| { - let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty); - self.predicate_must_hold_modulo_regions(&obligation) - }; let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 81ce58a93fa..9af85f5e3f0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -80,11 +80,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } Some(LangItem::DiscriminantKind) => { // `DiscriminantKind` is automatically implemented for every type. - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } Some(LangItem::PointeeTrait) => { // `Pointee` is automatically implemented for every type. - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } Some(LangItem::Sized) => { self.assemble_builtin_sized_candidate( @@ -365,7 +365,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",); - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } } @@ -810,7 +810,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { hir::Movability::Movable => { // Movable coroutines are always `Unpin`, so add an // unconditional builtin candidate. - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } } } @@ -1122,10 +1122,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { sizedness: SizedTraitKind, ) { match self.sizedness_conditions(obligation, sizedness) { - BuiltinImplConditions::Where(nested) => { - candidates - .vec - .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() }); + BuiltinImplConditions::Where(_nested) => { + candidates.vec.push(SizedCandidate); } BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { @@ -1143,10 +1141,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { match conditions { - BuiltinImplConditions::Where(nested) => { - candidates - .vec - .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() }); + BuiltinImplConditions::Where(_) => { + candidates.vec.push(BuiltinCandidate); } BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { @@ -1160,7 +1156,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } fn assemble_candidate_for_tuple( @@ -1171,7 +1167,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); match self_ty.kind() { ty::Tuple(_) => { - candidates.vec.push(BuiltinCandidate { has_nested: false }); + candidates.vec.push(BuiltinCandidate); } ty::Infer(ty::TyVar(_)) => { candidates.ambiguous = true; @@ -1215,7 +1211,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty()); match self_ty.skip_binder().kind() { - ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }), + ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a6b77583fdc..545531f927a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -37,13 +37,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> Result<Selection<'tcx>, SelectionError<'tcx>> { Ok(match candidate { - SizedCandidate { has_nested } => { - let data = self.confirm_builtin_candidate(obligation, has_nested); + SizedCandidate => { + let data = self.confirm_builtin_candidate(obligation); ImplSource::Builtin(BuiltinImplSource::Misc, data) } - BuiltinCandidate { has_nested } => { - let data = self.confirm_builtin_candidate(obligation, has_nested); + BuiltinCandidate => { + let data = self.confirm_builtin_candidate(obligation); ImplSource::Builtin(BuiltinImplSource::Misc, data) } @@ -249,50 +249,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[instrument(level = "debug", skip(self), ret)] fn confirm_builtin_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - has_nested: bool, ) -> PredicateObligations<'tcx> { - debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); - + debug!(?obligation, "confirm_builtin_candidate"); let tcx = self.tcx(); - let obligations = if has_nested { - let trait_def = obligation.predicate.def_id(); - let conditions = match tcx.as_lang_item(trait_def) { - Some(LangItem::Sized) => { - self.sizedness_conditions(obligation, SizedTraitKind::Sized) - } - Some(LangItem::MetaSized) => { - self.sizedness_conditions(obligation, SizedTraitKind::MetaSized) - } - Some(LangItem::PointeeSized) => { - bug!("`PointeeSized` is removing during lowering"); - } - Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation), - Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation), - other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"), - }; - let BuiltinImplConditions::Where(types) = conditions else { - bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation); - }; - let types = self.infcx.enter_forall_and_leak_universe(types); - - let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); - self.collect_predicates_for_types( - obligation.param_env, - cause, - obligation.recursion_depth + 1, - trait_def, - types, - ) - } else { - PredicateObligations::new() + let trait_def = obligation.predicate.def_id(); + let conditions = match tcx.as_lang_item(trait_def) { + Some(LangItem::Sized) => self.sizedness_conditions(obligation, SizedTraitKind::Sized), + Some(LangItem::MetaSized) => { + self.sizedness_conditions(obligation, SizedTraitKind::MetaSized) + } + Some(LangItem::PointeeSized) => { + bug!("`PointeeSized` is removing during lowering"); + } + Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation), + Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation), + Some( + LangItem::Destruct + | LangItem::DiscriminantKind + | LangItem::FnPtrTrait + | LangItem::PointeeTrait + | LangItem::Tuple + | LangItem::Unpin, + ) => BuiltinImplConditions::Where(ty::Binder::dummy(vec![])), + other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"), }; + let BuiltinImplConditions::Where(types) = conditions else { + bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation); + }; + let types = self.infcx.enter_forall_and_leak_universe(types); - debug!(?obligations); - - obligations + let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); + self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def, + types, + ) } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index af3641c22ed..c9930c69b32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1834,7 +1834,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We prefer `Sized` candidates over everything. let mut sized_candidates = - candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ })); + candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); if let Some(sized_candidate) = sized_candidates.next() { // There should only ever be a single sized candidate // as they would otherwise overlap. @@ -1986,8 +1986,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Don't use impl candidates which overlap with other candidates. // This should pretty much only ever happen with malformed impls. if candidates.iter().all(|c| match c.candidate { - SizedCandidate { has_nested: _ } - | BuiltinCandidate { has_nested: _ } + SizedCandidate + | BuiltinCandidate | TransmutabilityCandidate | AutoImplCandidate | ClosureCandidate { .. } diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 150f5d118e0..3f83b4d50aa 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -296,7 +296,7 @@ pub(crate) mod rustc { } let target = cx.data_layout(); - let pointer_size = target.pointer_size; + let pointer_size = target.pointer_size(); match ty.kind() { ty::Bool => Ok(Self::bool()), diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 2fb3c5ff945..6a9461f2b43 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -177,6 +177,17 @@ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> { } } +struct DisambiguatorIdxVisitor { + depth: u32, +} + +impl<'tcx> Visitor<'tcx> for DisambiguatorIdxVisitor { + fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result { + self.depth += 1; + intravisit::walk_opaque_ty(self, opaque) + } +} + /// Given an `fn_def_id` of a trait or a trait implementation: /// /// if `fn_def_id` is a function defined inside a trait, then it synthesizes @@ -211,16 +222,19 @@ fn associated_types_for_impl_traits_in_associated_fn( let disambiguator_idx = trait_item_refs .iter() .take_while(|item| item.id.owner_id.def_id != fn_def_id) - .fold(0, |acc, item| { - if !matches!(item.kind, hir::AssocItemKind::Fn { .. }) { - acc - } else if def_path_id(item.id.owner_id.def_id) == def_path_data { - tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator - + 1 - } else { - acc - } - }); + .filter(|item| { + matches!(item.kind, hir::AssocItemKind::Fn { .. }) + && def_path_id(item.id.owner_id.def_id) == def_path_data + }) + .last() + .map(|item| { + let output = tcx.hir_get_fn_output(item.id.owner_id.def_id).unwrap(); + let mut visitor = DisambiguatorIdxVisitor { depth: 0 }; + visitor.visit_fn_ret_ty(output); + tcx.def_key(item.id.owner_id.def_id).disambiguated_data.disambiguator + + visitor.depth + }) + .unwrap_or_default(); let data = DefPathData::AnonAssocTy(def_path_data); let mut visitor = RPITVisitor { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index a225b712d4b..163e2b30883 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -379,7 +379,7 @@ fn layout_of_uncached<'tcx>( // Potentially-wide pointers. ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { - let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA)); + let mut data_ptr = scalar_unit(Pointer(AddressSpace::ZERO)); if !ty.is_raw_ptr() { data_ptr.valid_range_mut().start = 1; } @@ -435,7 +435,7 @@ fn layout_of_uncached<'tcx>( } ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), ty::Dynamic(..) => { - let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); + let mut vtable = scalar_unit(Pointer(AddressSpace::ZERO)); vtable.valid_range_mut().start = 1; vtable } diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml index 516c8e9c718..6777abce01d 100644 --- a/compiler/stable_mir/Cargo.toml +++ b/compiler/stable_mir/Cargo.toml @@ -4,7 +4,18 @@ version = "0.1.0-preview" edition = "2024" [dependencies] +# tidy-alphabetical-start +rustc_abi = { path = "../rustc_abi" } +rustc_hir = { path = "../rustc_hir" } +rustc_middle = { path = "../rustc_middle" } +rustc_session = { path = "../rustc_session" } rustc_smir = { path = "../rustc_smir" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } +scoped-tls = "1.0" +serde = { version = "1.0.125", features = [ "derive" ] } +tracing = "0.1" +# tidy-alphabetical-end [features] # Provides access to APIs that expose internals of the rust compiler. diff --git a/compiler/rustc_smir/src/stable_mir/abi.rs b/compiler/stable_mir/src/abi.rs index 369d08e444e..7b0882caf1b 100644 --- a/compiler/rustc_smir/src/stable_mir/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -3,13 +3,12 @@ use std::num::NonZero; use std::ops::RangeInclusive; use serde::Serialize; -use stable_mir::compiler_interface::with; -use stable_mir::mir::FieldIdx; -use stable_mir::target::{MachineInfo, MachineSize as Size}; -use stable_mir::ty::{Align, Ty, VariantIdx}; -use stable_mir::{Error, Opaque, error}; -use crate::stable_mir; +use crate::compiler_interface::with; +use crate::mir::FieldIdx; +use crate::target::{MachineInfo, MachineSize as Size}; +use crate::ty::{Align, Ty, VariantIdx}; +use crate::{Error, Opaque, error}; /// A function ABI definition. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] @@ -119,7 +118,7 @@ impl Layout { } } -impl stable_mir::IndexedVal for Layout { +impl crate::IndexedVal for Layout { fn to_val(index: usize) -> Self { Layout(index) } diff --git a/compiler/rustc_smir/src/stable_mir/alloc.rs b/compiler/stable_mir/src/alloc.rs index 120cb4404b9..349b83231e3 100644 --- a/compiler/rustc_smir/src/stable_mir/alloc.rs +++ b/compiler/stable_mir/src/alloc.rs @@ -16,7 +16,6 @@ use super::compiler_interface::BridgeTys; use super::mir::Mutability; use super::ty::{Allocation, ProvenanceMap}; use super::unstable::Stable; -use crate::rustc_smir; /// Creates new empty `Allocation` from given `Align`. fn new_empty_allocation(align: Align) -> Allocation { diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index a19968d2ab7..50c2f02e6ad 100644 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -8,68 +8,67 @@ use std::cell::Cell; use rustc_hir::def::DefKind; use rustc_smir::context::SmirCtxt; use rustc_smir::{Bridge, SmirContainer}; -use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; -use stable_mir::crate_def::Attribute; -use stable_mir::mir::alloc::{AllocId, GlobalAlloc}; -use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; -use stable_mir::mir::{BinOp, Body, Place, UnOp}; -use stable_mir::target::{MachineInfo, MachineSize}; -use stable_mir::ty::{ +use tracing::debug; + +use crate::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; +use crate::crate_def::Attribute; +use crate::mir::alloc::{AllocId, GlobalAlloc}; +use crate::mir::mono::{Instance, InstanceDef, StaticDef}; +use crate::mir::{BinOp, Body, Place, UnOp}; +use crate::target::{MachineInfo, MachineSize}; +use crate::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, }; -use stable_mir::unstable::{RustcInternal, Stable, new_item_kind}; -use stable_mir::{ +use crate::unstable::{RustcInternal, Stable, new_item_kind}; +use crate::{ AssocItems, Crate, CrateDef, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol, TraitDecls, alloc, mir, }; -use tracing::debug; - -use crate::{rustc_smir, stable_mir}; pub struct BridgeTys; impl Bridge for BridgeTys { - type DefId = stable_mir::DefId; - type AllocId = stable_mir::mir::alloc::AllocId; - type Span = stable_mir::ty::Span; - type Ty = stable_mir::ty::Ty; - type InstanceDef = stable_mir::mir::mono::InstanceDef; - type TyConstId = stable_mir::ty::TyConstId; - type MirConstId = stable_mir::ty::MirConstId; - type Layout = stable_mir::abi::Layout; - - type Error = stable_mir::Error; - type CrateItem = stable_mir::CrateItem; - type AdtDef = stable_mir::ty::AdtDef; - type ForeignModuleDef = stable_mir::ty::ForeignModuleDef; - type ForeignDef = stable_mir::ty::ForeignDef; - type FnDef = stable_mir::ty::FnDef; - type ClosureDef = stable_mir::ty::ClosureDef; - type CoroutineDef = stable_mir::ty::CoroutineDef; - type CoroutineClosureDef = stable_mir::ty::CoroutineClosureDef; - type AliasDef = stable_mir::ty::AliasDef; - type ParamDef = stable_mir::ty::ParamDef; - type BrNamedDef = stable_mir::ty::BrNamedDef; - type TraitDef = stable_mir::ty::TraitDef; - type GenericDef = stable_mir::ty::GenericDef; - type ConstDef = stable_mir::ty::ConstDef; - type ImplDef = stable_mir::ty::ImplDef; - type RegionDef = stable_mir::ty::RegionDef; - type CoroutineWitnessDef = stable_mir::ty::CoroutineWitnessDef; - type AssocDef = stable_mir::ty::AssocDef; - type OpaqueDef = stable_mir::ty::OpaqueDef; - type Prov = stable_mir::ty::Prov; - type StaticDef = stable_mir::mir::mono::StaticDef; - - type Allocation = stable_mir::ty::Allocation; + type DefId = crate::DefId; + type AllocId = crate::mir::alloc::AllocId; + type Span = crate::ty::Span; + type Ty = crate::ty::Ty; + type InstanceDef = crate::mir::mono::InstanceDef; + type TyConstId = crate::ty::TyConstId; + type MirConstId = crate::ty::MirConstId; + type Layout = crate::abi::Layout; + + type Error = crate::Error; + type CrateItem = crate::CrateItem; + type AdtDef = crate::ty::AdtDef; + type ForeignModuleDef = crate::ty::ForeignModuleDef; + type ForeignDef = crate::ty::ForeignDef; + type FnDef = crate::ty::FnDef; + type ClosureDef = crate::ty::ClosureDef; + type CoroutineDef = crate::ty::CoroutineDef; + type CoroutineClosureDef = crate::ty::CoroutineClosureDef; + type AliasDef = crate::ty::AliasDef; + type ParamDef = crate::ty::ParamDef; + type BrNamedDef = crate::ty::BrNamedDef; + type TraitDef = crate::ty::TraitDef; + type GenericDef = crate::ty::GenericDef; + type ConstDef = crate::ty::ConstDef; + type ImplDef = crate::ty::ImplDef; + type RegionDef = crate::ty::RegionDef; + type CoroutineWitnessDef = crate::ty::CoroutineWitnessDef; + type AssocDef = crate::ty::AssocDef; + type OpaqueDef = crate::ty::OpaqueDef; + type Prov = crate::ty::Prov; + type StaticDef = crate::mir::mono::StaticDef; + + type Allocation = crate::ty::Allocation; } /// Stable public API for querying compiler information. /// -/// All queries are delegated to [`crate::rustc_smir::context::SmirCtxt`] that provides +/// All queries are delegated to [`rustc_smir::context::SmirCtxt`] that provides /// similar APIs but based on internal rustc constructs. /// /// Do not use this directly. This is currently used in the macro expansion. @@ -440,7 +439,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> { let cx = &*self.cx.borrow(); let did = tables[def_id]; let (parent, kinds) = cx.predicates_of(did); - stable_mir::ty::GenericPredicates { + crate::ty::GenericPredicates { parent: parent.map(|did| tables.trait_def(did)), predicates: kinds .iter() @@ -454,7 +453,7 @@ impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> { let cx = &*self.cx.borrow(); let did = tables[def_id]; let (parent, kinds) = cx.explicit_predicates_of(did); - stable_mir::ty::GenericPredicates { + crate::ty::GenericPredicates { parent: parent.map(|did| tables.trait_def(did)), predicates: kinds .iter() diff --git a/compiler/rustc_smir/src/stable_mir/crate_def.rs b/compiler/stable_mir/src/crate_def.rs index 64f7ef9b314..75228135e4c 100644 --- a/compiler/rustc_smir/src/stable_mir/crate_def.rs +++ b/compiler/stable_mir/src/crate_def.rs @@ -2,10 +2,9 @@ //! such as, a function, a trait, an enum, and any other definitions. use serde::Serialize; -use stable_mir::ty::{GenericArgs, Span, Ty}; -use stable_mir::{AssocItems, Crate, Symbol, with}; -use crate::stable_mir; +use crate::ty::{GenericArgs, Span, Ty}; +use crate::{AssocItems, Crate, Symbol, with}; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)] diff --git a/compiler/rustc_smir/src/stable_mir/error.rs b/compiler/stable_mir/src/error.rs index 3f9d67954b9..702134b0c4c 100644 --- a/compiler/rustc_smir/src/stable_mir/error.rs +++ b/compiler/stable_mir/src/error.rs @@ -9,8 +9,6 @@ use std::{fmt, io}; use rustc_smir::bridge::SmirError; -use crate::rustc_smir; - macro_rules! error { ($fmt: literal $(,)?) => { Error(format!($fmt)) }; ($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg)*)) }; diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 688f3936b26..0a2e4e71afc 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -1,11 +1,300 @@ -//! We've temporarily moved the `stable_mir` implementation to [`rustc_smir::stable_mir`], -//! during refactoring to break the circular dependency between `rustc_smir` and `stable_mir`, +//! The WIP stable interface to rustc internals. //! -//! This is a transitional measure as described in [PR #139319](https://github.com/rust-lang/rust/pull/139319). -//! Once the refactoring is complete, the `stable_mir` implementation will be moved back here. +//! For more information see <https://github.com/rust-lang/project-stable-mir> +//! +//! # Note +//! +//! This API is still completely unstable and subject to change. +#![allow(rustc::usage_of_ty_tykind)] +#![doc( + html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", + test(attr(allow(unused_variables), deny(warnings))) +)] +#![feature(sized_hierarchy)] +//! +//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to +//! interact with the compiler. +//! +//! The goal is to eventually be published on +//! [crates.io](https://crates.io). + +use std::fmt::Debug; +use std::{fmt, io}; + +pub(crate) use rustc_smir::IndexedVal; +use rustc_smir::Tables; +use rustc_smir::context::SmirCtxt; /// Export the rustc_internal APIs. Note that this module has no stability /// guarantees and it is not taken into account for semver. #[cfg(feature = "rustc_internal")] -pub use rustc_smir::rustc_internal; -pub use rustc_smir::stable_mir::*; +pub mod rustc_internal; +use serde::Serialize; + +use crate::compiler_interface::with; +pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId}; +pub use crate::error::*; +use crate::mir::mono::StaticDef; +use crate::mir::{Body, Mutability}; +use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, ProvenanceMap, Span, TraitDef, Ty}; +use crate::unstable::Stable; + +pub mod abi; +mod alloc; +pub(crate) mod unstable; +#[macro_use] +pub mod crate_def; +pub mod compiler_interface; +#[macro_use] +pub mod error; +pub mod mir; +pub mod target; +pub mod ty; +pub mod visitor; + +/// Use String for now but we should replace it. +pub type Symbol = String; + +/// The number that identifies a crate. +pub type CrateNum = usize; + +impl Debug for DefId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish() + } +} + +impl IndexedVal for DefId { + fn to_val(index: usize) -> Self { + DefId(index) + } + + fn to_index(&self) -> usize { + self.0 + } +} + +/// A list of crate items. +pub type CrateItems = Vec<CrateItem>; + +/// A list of trait decls. +pub type TraitDecls = Vec<TraitDef>; + +/// A list of impl trait decls. +pub type ImplTraitDecls = Vec<ImplDef>; + +/// A list of associated items. +pub type AssocItems = Vec<AssocItem>; + +/// Holds information about a crate. +#[derive(Clone, PartialEq, Eq, Debug, Serialize)] +pub struct Crate { + pub id: CrateNum, + pub name: Symbol, + pub is_local: bool, +} + +impl Crate { + /// The list of foreign modules in this crate. + pub fn foreign_modules(&self) -> Vec<ForeignModuleDef> { + with(|cx| cx.foreign_modules(self.id)) + } + + /// The list of traits declared in this crate. + pub fn trait_decls(&self) -> TraitDecls { + with(|cx| cx.trait_decls(self.id)) + } + + /// The list of trait implementations in this crate. + pub fn trait_impls(&self) -> ImplTraitDecls { + with(|cx| cx.trait_impls(self.id)) + } + + /// Return a list of function definitions from this crate independent on their visibility. + pub fn fn_defs(&self) -> Vec<FnDef> { + with(|cx| cx.crate_functions(self.id)) + } + + /// Return a list of static items defined in this crate independent on their visibility. + pub fn statics(&self) -> Vec<StaticDef> { + with(|cx| cx.crate_statics(self.id)) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum ItemKind { + Fn, + Static, + Const, + Ctor(CtorKind), +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)] +pub enum CtorKind { + Const, + Fn, +} + +pub type Filename = String; + +crate_def_with_ty! { + /// Holds information about an item in a crate. + #[derive(Serialize)] + pub CrateItem; +} + +impl CrateItem { + /// This will return the body of an item or panic if it's not available. + pub fn expect_body(&self) -> mir::Body { + with(|cx| cx.mir_body(self.0)) + } + + /// Return the body of an item if available. + pub fn body(&self) -> Option<mir::Body> { + with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0))) + } + + /// Check if a body is available for this item. + pub fn has_body(&self) -> bool { + with(|cx| cx.has_body(self.0)) + } + + pub fn span(&self) -> Span { + with(|cx| cx.span_of_an_item(self.0)) + } + + pub fn kind(&self) -> ItemKind { + with(|cx| cx.item_kind(*self)) + } + + pub fn requires_monomorphization(&self) -> bool { + with(|cx| cx.requires_monomorphization(self.0)) + } + + pub fn ty(&self) -> Ty { + with(|cx| cx.def_ty(self.0)) + } + + pub fn is_foreign_item(&self) -> bool { + with(|cx| cx.is_foreign_item(self.0)) + } + + /// Emit MIR for this item body. + pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> { + self.body() + .ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))? + .dump(w, &self.name()) + } +} + +/// Return the function where execution starts if the current +/// crate defines that. This is usually `main`, but could be +/// `start` if the crate is a no-std crate. +pub fn entry_fn() -> Option<CrateItem> { + with(|cx| cx.entry_fn()) +} + +/// Access to the local crate. +pub fn local_crate() -> Crate { + with(|cx| cx.local_crate()) +} + +/// Try to find a crate or crates if multiple crates exist from given name. +pub fn find_crates(name: &str) -> Vec<Crate> { + with(|cx| cx.find_crates(name)) +} + +/// Try to find a crate with the given name. +pub fn external_crates() -> Vec<Crate> { + with(|cx| cx.external_crates()) +} + +/// Retrieve all items in the local crate that have a MIR associated with them. +pub fn all_local_items() -> CrateItems { + with(|cx| cx.all_local_items()) +} + +pub fn all_trait_decls() -> TraitDecls { + with(|cx| cx.all_trait_decls()) +} + +pub fn all_trait_impls() -> ImplTraitDecls { + with(|cx| cx.all_trait_impls()) +} + +/// A type that provides internal information but that can still be used for debug purpose. +#[derive(Clone, PartialEq, Eq, Hash, Serialize)] +pub struct Opaque(String); + +impl std::fmt::Display for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +pub fn opaque<T: Debug>(value: &T) -> Opaque { + Opaque(format!("{value:?}")) +} + +macro_rules! bridge_impl { + ($name: ident, $ty: ty) => { + impl rustc_smir::bridge::$name<compiler_interface::BridgeTys> for $ty { + fn new(def: crate::DefId) -> Self { + Self(def) + } + } + }; +} + +bridge_impl!(CrateItem, crate::CrateItem); +bridge_impl!(AdtDef, crate::ty::AdtDef); +bridge_impl!(ForeignModuleDef, crate::ty::ForeignModuleDef); +bridge_impl!(ForeignDef, crate::ty::ForeignDef); +bridge_impl!(FnDef, crate::ty::FnDef); +bridge_impl!(ClosureDef, crate::ty::ClosureDef); +bridge_impl!(CoroutineDef, crate::ty::CoroutineDef); +bridge_impl!(CoroutineClosureDef, crate::ty::CoroutineClosureDef); +bridge_impl!(AliasDef, crate::ty::AliasDef); +bridge_impl!(ParamDef, crate::ty::ParamDef); +bridge_impl!(BrNamedDef, crate::ty::BrNamedDef); +bridge_impl!(TraitDef, crate::ty::TraitDef); +bridge_impl!(GenericDef, crate::ty::GenericDef); +bridge_impl!(ConstDef, crate::ty::ConstDef); +bridge_impl!(ImplDef, crate::ty::ImplDef); +bridge_impl!(RegionDef, crate::ty::RegionDef); +bridge_impl!(CoroutineWitnessDef, crate::ty::CoroutineWitnessDef); +bridge_impl!(AssocDef, crate::ty::AssocDef); +bridge_impl!(OpaqueDef, crate::ty::OpaqueDef); +bridge_impl!(StaticDef, crate::mir::mono::StaticDef); + +impl rustc_smir::bridge::Prov<compiler_interface::BridgeTys> for crate::ty::Prov { + fn new(aid: crate::mir::alloc::AllocId) -> Self { + Self(aid) + } +} + +impl rustc_smir::bridge::Allocation<compiler_interface::BridgeTys> for crate::ty::Allocation { + fn new<'tcx>( + bytes: Vec<Option<u8>>, + ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>, + align: u64, + mutability: rustc_middle::mir::Mutability, + tables: &mut Tables<'tcx, compiler_interface::BridgeTys>, + cx: &SmirCtxt<'tcx, compiler_interface::BridgeTys>, + ) -> Self { + Self { + bytes, + provenance: ProvenanceMap { + ptrs: ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect(), + }, + align, + mutability: mutability.stable(tables, cx), + } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mir.rs b/compiler/stable_mir/src/mir.rs index 413b5152bb3..413b5152bb3 100644 --- a/compiler/rustc_smir/src/stable_mir/mir.rs +++ b/compiler/stable_mir/src/mir.rs diff --git a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs b/compiler/stable_mir/src/mir/alloc.rs index 26f30898a9c..0d45e59885c 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs +++ b/compiler/stable_mir/src/mir/alloc.rs @@ -3,12 +3,11 @@ use std::io::Read; use serde::Serialize; -use stable_mir::mir::mono::{Instance, StaticDef}; -use stable_mir::target::{Endian, MachineInfo}; -use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, Ty}; -use stable_mir::{Error, IndexedVal, with}; -use crate::stable_mir; +use crate::mir::mono::{Instance, StaticDef}; +use crate::target::{Endian, MachineInfo}; +use crate::ty::{Allocation, Binder, ExistentialTraitRef, Ty}; +use crate::{Error, IndexedVal, with}; /// An allocation in the SMIR global memory can be either a function pointer, /// a static, or a "real" allocation with some data in it. diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 90d4a06b177..a9fe3607232 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,15 +1,14 @@ use std::io; use serde::Serialize; -use stable_mir::compiler_interface::with; -use stable_mir::mir::pretty::function_body; -use stable_mir::ty::{ + +use crate::compiler_interface::with; +use crate::mir::pretty::function_body; +use crate::ty::{ AdtDef, ClosureDef, CoroutineClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty, TyConst, TyKind, VariantIdx, }; -use stable_mir::{Error, Opaque, Span, Symbol}; - -use crate::stable_mir; +use crate::{Error, Opaque, Span, Symbol}; /// The SMIR representation of a single function. #[derive(Clone, Debug, Serialize)] @@ -587,7 +586,7 @@ pub enum Rvalue { /// /// **Needs clarification**: Are there weird additional semantics here related to the runtime /// nature of this operation? - ThreadLocalRef(stable_mir::CrateItem), + ThreadLocalRef(crate::CrateItem), /// Computes a value as described by the operation. NullaryOp(NullOp, Ty), diff --git a/compiler/rustc_smir/src/stable_mir/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 5f177416714..c54fcecac9f 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -3,13 +3,12 @@ use std::io; use rustc_smir::bridge::SmirError; use serde::Serialize; -use stable_mir::abi::FnAbi; -use stable_mir::crate_def::CrateDef; -use stable_mir::mir::Body; -use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, Ty}; -use stable_mir::{CrateItem, DefId, Error, IndexedVal, ItemKind, Opaque, Symbol, with}; -use crate::{rustc_smir, stable_mir}; +use crate::abi::FnAbi; +use crate::crate_def::CrateDef; +use crate::mir::Body; +use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, Ty}; +use crate::{CrateItem, DefId, Error, IndexedVal, ItemKind, Opaque, Symbol, with}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum MonoItem { @@ -194,7 +193,7 @@ impl Debug for Instance { /// Try to convert a crate item into an instance. /// The item cannot be generic in order to be converted into an instance. impl TryFrom<CrateItem> for Instance { - type Error = stable_mir::Error; + type Error = crate::Error; fn try_from(item: CrateItem) -> Result<Self, Self::Error> { with(|context| { @@ -211,7 +210,7 @@ impl TryFrom<CrateItem> for Instance { /// Try to convert an instance into a crate item. /// Only user defined instances can be converted. impl TryFrom<Instance> for CrateItem { - type Error = stable_mir::Error; + type Error = crate::Error; fn try_from(value: Instance) -> Result<Self, Self::Error> { with(|context| { @@ -258,7 +257,7 @@ crate_def! { } impl TryFrom<CrateItem> for StaticDef { - type Error = stable_mir::Error; + type Error = crate::Error; fn try_from(value: CrateItem) -> Result<Self, Self::Error> { if matches!(value.kind(), ItemKind::Static) { @@ -270,7 +269,7 @@ impl TryFrom<CrateItem> for StaticDef { } impl TryFrom<Instance> for StaticDef { - type Error = stable_mir::Error; + type Error = crate::Error; fn try_from(value: Instance) -> Result<Self, Self::Error> { StaticDef::try_from(CrateItem::try_from(value)?) diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index a7347e9b021..f496d80053e 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -4,14 +4,13 @@ use std::io::Write; use std::{fmt, io, iter}; use fmt::{Display, Formatter}; -use stable_mir::mir::{ - Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, -}; -use stable_mir::ty::{AdtKind, AssocKind, MirConst, Ty, TyConst}; -use stable_mir::{Body, CrateDef, IndexedVal, Mutability, with}; use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind}; -use crate::stable_mir; +use crate::mir::{ + Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents, +}; +use crate::ty::{AdtKind, AssocKind, MirConst, Ty, TyConst}; +use crate::{Body, CrateDef, IndexedVal, Mutability, with}; impl Display for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { diff --git a/compiler/rustc_smir/src/stable_mir/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index b7dd433eb09..7dc99d1d1e1 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -35,11 +35,9 @@ //! The only place that `_` is acceptable is to match a field (or //! variant argument) that does not require visiting. -use stable_mir::mir::*; -use stable_mir::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; -use stable_mir::{Error, Opaque, Span}; - -use crate::stable_mir; +use crate::mir::*; +use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; +use crate::{Error, Opaque, Span}; macro_rules! make_mir_visitor { ($visitor_trait_name:ident, $($mutability:ident)?) => { diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/stable_mir/src/rustc_internal/mod.rs index dcdc77b76c2..c1ed03ade75 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/stable_mir/src/rustc_internal/mod.rs @@ -6,14 +6,13 @@ use std::cell::{Cell, RefCell}; use rustc_middle::ty::TyCtxt; +use rustc_smir::context::SmirCtxt; +use rustc_smir::{Bridge, SmirContainer, Tables}; use rustc_span::def_id::CrateNum; use scoped_tls::scoped_thread_local; -use stable_mir::Error; -use stable_mir::unstable::{RustcInternal, Stable}; -use crate::rustc_smir::context::SmirCtxt; -use crate::rustc_smir::{Bridge, SmirContainer, Tables}; -use crate::stable_mir; +use crate::Error; +use crate::unstable::{RustcInternal, Stable}; pub mod pretty; @@ -53,7 +52,7 @@ where with_container(|tables, _| item.internal(tables, tcx)) } -pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { +pub fn crate_num(item: &crate::Crate) -> CrateNum { item.id.into() } @@ -93,7 +92,7 @@ where let smir_cx = RefCell::new(SmirCtxt::new(tcx)); let container = SmirContainer { tables: RefCell::new(Tables::default()), cx: smir_cx }; - stable_mir::compiler_interface::run(&container, || init(&container, f)) + crate::compiler_interface::run(&container, || init(&container, f)) } /// Instantiate and run the compiler with the provided arguments and callback. @@ -106,7 +105,6 @@ where /// # extern crate rustc_interface; /// # extern crate rustc_middle; /// # #[macro_use] -/// # extern crate rustc_smir; /// # extern crate stable_mir; /// # /// # fn main() { @@ -127,7 +125,6 @@ where /// # extern crate rustc_interface; /// # extern crate rustc_middle; /// # #[macro_use] -/// # extern crate rustc_smir; /// # extern crate stable_mir; /// # /// # fn main() { @@ -190,7 +187,7 @@ macro_rules! run_driver { use rustc_driver::{Callbacks, Compilation, run_compiler}; use rustc_middle::ty::TyCtxt; use rustc_interface::interface; - use rustc_smir::rustc_internal; + use stable_mir::rustc_internal; use stable_mir::CompilerError; use std::ops::ControlFlow; diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/stable_mir/src/rustc_internal/pretty.rs index 0710c18746a..28c5280fe04 100644 --- a/compiler/rustc_smir/src/rustc_internal/pretty.rs +++ b/compiler/stable_mir/src/rustc_internal/pretty.rs @@ -3,7 +3,6 @@ use std::io; use rustc_middle::ty::TyCtxt; use super::run; -use crate::stable_mir; pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> { writeln!( @@ -15,7 +14,7 @@ pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io "// If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir." )?; let _ = run(tcx, || { - let items = stable_mir::all_local_items(); + let items = crate::all_local_items(); let _ = items.iter().map(|item| -> io::Result<()> { item.emit_mir(w) }).collect::<Vec<_>>(); }); Ok(()) diff --git a/compiler/rustc_smir/src/stable_mir/target.rs b/compiler/stable_mir/src/target.rs index 6cf1e9feb01..32c3a2a9122 100644 --- a/compiler/rustc_smir/src/stable_mir/target.rs +++ b/compiler/stable_mir/src/target.rs @@ -1,9 +1,8 @@ //! Provide information about the machine that this is being compiled into. use serde::Serialize; -use stable_mir::compiler_interface::with; -use crate::stable_mir; +use crate::compiler_interface::with; /// The properties of the target machine being compiled into. #[derive(Clone, PartialEq, Eq, Serialize)] diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/stable_mir/src/ty.rs index 004a7c02234..87d31cf9713 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -2,17 +2,16 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; use serde::Serialize; -use stable_mir::abi::{FnAbi, Layout}; -use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType}; -use stable_mir::mir::alloc::{AllocId, read_target_int, read_target_uint}; -use stable_mir::mir::mono::StaticDef; -use stable_mir::target::MachineInfo; -use stable_mir::{Filename, IndexedVal, Opaque}; use super::abi::ReprOptions; use super::mir::{Body, Mutability, Safety}; use super::{DefId, Error, Symbol, with}; -use crate::stable_mir; +use crate::abi::{FnAbi, Layout}; +use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType}; +use crate::mir::alloc::{AllocId, read_target_int, read_target_uint}; +use crate::mir::mono::StaticDef; +use crate::target::MachineInfo; +use crate::{Filename, IndexedVal, Opaque}; #[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)] pub struct Ty(usize); @@ -1565,7 +1564,7 @@ pub enum PredicatePolarity { macro_rules! index_impl { ($name:ident) => { - impl stable_mir::IndexedVal for $name { + impl crate::IndexedVal for $name { fn to_val(index: usize) -> Self { $name(index) } diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs b/compiler/stable_mir/src/unstable/convert/internal.rs index 37c93af392e..04b2e572621 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs +++ b/compiler/stable_mir/src/unstable/convert/internal.rs @@ -7,21 +7,20 @@ use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy}; use rustc_smir::Tables; -use stable_mir::abi::Layout; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::mir::alloc::AllocId; -use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; -use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; -use stable_mir::ty::{ + +use crate::abi::Layout; +use crate::compiler_interface::BridgeTys; +use crate::mir::alloc::AllocId; +use crate::mir::mono::{Instance, MonoItem, StaticDef}; +use crate::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; +use crate::ty::{ Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, }; -use stable_mir::unstable::{InternalCx, RustcInternal}; -use stable_mir::{CrateItem, CrateNum, DefId, IndexedVal}; - -use crate::{rustc_smir, stable_mir}; +use crate::unstable::{InternalCx, RustcInternal}; +use crate::{CrateItem, CrateNum, DefId, IndexedVal}; impl RustcInternal for CrateItem { type T<'tcx> = rustc_span::def_id::DefId; @@ -505,7 +504,7 @@ impl RustcInternal for ExistentialProjection { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - use rustc_smir::context::SmirExistentialProjection; + use crate::unstable::internal_cx::SmirExistentialProjection; tcx.new_from_args( self.def_id.0.internal(tables, tcx), self.generic_args.internal(tables, tcx), @@ -537,7 +536,7 @@ impl RustcInternal for ExistentialTraitRef { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - use rustc_smir::context::SmirExistentialTraitRef; + use crate::unstable::internal_cx::SmirExistentialTraitRef; tcx.new_from_args( self.def_id.0.internal(tables, tcx), self.generic_args.internal(tables, tcx), @@ -553,7 +552,7 @@ impl RustcInternal for TraitRef { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - use rustc_smir::context::SmirTraitRef; + use crate::unstable::internal_cx::SmirTraitRef; tcx.new_from_args(self.def_id.0.internal(tables, tcx), self.args().internal(tables, tcx)) } } diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs b/compiler/stable_mir/src/unstable/convert/mod.rs index 6e1b85671f8..aad92325861 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs +++ b/compiler/stable_mir/src/unstable/convert/mod.rs @@ -10,10 +10,9 @@ use std::ops::RangeInclusive; use rustc_smir::Tables; use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; use super::Stable; -use crate::{rustc_smir, stable_mir}; +use crate::compiler_interface::BridgeTys; mod internal; mod stable; diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs b/compiler/stable_mir/src/unstable/convert/stable/abi.rs index d8823a0d10c..8fdaa69c305 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs +++ b/compiler/stable_mir/src/unstable/convert/stable/abi.rs @@ -7,18 +7,17 @@ use rustc_middle::ty; use rustc_smir::Tables; use rustc_smir::context::SmirCtxt; use rustc_target::callconv; -use stable_mir::abi::{ + +use crate::abi::{ AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange, }; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::target::MachineSize as Size; -use stable_mir::ty::{Align, VariantIdx}; -use stable_mir::unstable::Stable; -use stable_mir::{IndexedVal, opaque}; - -use crate::{rustc_smir, stable_mir}; +use crate::compiler_interface::BridgeTys; +use crate::target::MachineSize as Size; +use crate::ty::{Align, VariantIdx}; +use crate::unstable::Stable; +use crate::{IndexedVal, opaque}; impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx { type T = VariantIdx; @@ -28,12 +27,12 @@ impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx { } impl<'tcx> Stable<'tcx> for rustc_abi::Endian { - type T = stable_mir::target::Endian; + type T = crate::target::Endian; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - rustc_abi::Endian::Little => stable_mir::target::Endian::Little, - rustc_abi::Endian::Big => stable_mir::target::Endian::Big, + rustc_abi::Endian::Little => crate::target::Endian::Little, + rustc_abi::Endian::Big => crate::target::Endian::Big, } } } diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs b/compiler/stable_mir/src/unstable/convert/stable/mir.rs index 99f9f456567..f6f4706e40b 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs +++ b/compiler/stable_mir/src/unstable/convert/stable/mir.rs @@ -5,27 +5,26 @@ use rustc_middle::{bug, mir}; use rustc_smir::Tables; use rustc_smir::bridge::SmirError; use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::mir::alloc::GlobalAlloc; -use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment}; -use stable_mir::ty::{Allocation, ConstantKind, MirConst}; -use stable_mir::unstable::Stable; -use stable_mir::{Error, alloc, opaque}; -use crate::{rustc_smir, stable_mir}; +use crate::compiler_interface::BridgeTys; +use crate::mir::alloc::GlobalAlloc; +use crate::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment}; +use crate::ty::{Allocation, ConstantKind, MirConst}; +use crate::unstable::Stable; +use crate::{Error, alloc, opaque}; impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { - type T = stable_mir::mir::Body; + type T = crate::mir::Body; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::mir::Body::new( + crate::mir::Body::new( self.basic_blocks .iter() - .map(|block| stable_mir::mir::BasicBlock { + .map(|block| crate::mir::BasicBlock { terminator: block.terminator().stable(tables, cx), statements: block .statements @@ -36,7 +35,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { .collect(), self.local_decls .iter() - .map(|decl| stable_mir::mir::LocalDecl { + .map(|decl| crate::mir::LocalDecl { ty: decl.ty.stable(tables, cx), span: decl.source_info.span.stable(tables, cx), mutability: decl.mutability.stable(tables, cx), @@ -51,13 +50,13 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { } impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> { - type T = stable_mir::mir::VarDebugInfo; + type T = crate::mir::VarDebugInfo; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::mir::VarDebugInfo { + crate::mir::VarDebugInfo { name: self.name.to_string(), source_info: self.source_info.stable(tables, cx), composite: self.composite.as_ref().map(|composite| composite.stable(tables, cx)), @@ -68,7 +67,7 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> { } impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { - type T = stable_mir::mir::Statement; + type T = crate::mir::Statement; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -82,18 +81,18 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { } impl<'tcx> Stable<'tcx> for mir::SourceInfo { - type T = stable_mir::mir::SourceInfo; + type T = crate::mir::SourceInfo; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() } + crate::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() } } } impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> { - type T = stable_mir::mir::VarDebugInfoFragment; + type T = crate::mir::VarDebugInfoFragment; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -107,7 +106,7 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> { } impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> { - type T = stable_mir::mir::VarDebugInfoContents; + type T = crate::mir::VarDebugInfoContents; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -115,7 +114,7 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> { ) -> Self::T { match self { mir::VarDebugInfoContents::Place(place) => { - stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables, cx)) + crate::mir::VarDebugInfoContents::Place(place.stable(tables, cx)) } mir::VarDebugInfoContents::Const(const_operand) => { let op = ConstOperand { @@ -123,81 +122,76 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> { user_ty: const_operand.user_ty.map(|index| index.as_usize()), const_: const_operand.const_.stable(tables, cx), }; - stable_mir::mir::VarDebugInfoContents::Const(op) + crate::mir::VarDebugInfoContents::Const(op) } } } } impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { - type T = stable_mir::mir::StatementKind; + type T = crate::mir::StatementKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { match self { - mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign( + mir::StatementKind::Assign(assign) => crate::mir::StatementKind::Assign( assign.0.stable(tables, cx), assign.1.stable(tables, cx), ), - mir::StatementKind::FakeRead(fake_read_place) => { - stable_mir::mir::StatementKind::FakeRead( - fake_read_place.0.stable(tables, cx), - fake_read_place.1.stable(tables, cx), - ) - } + mir::StatementKind::FakeRead(fake_read_place) => crate::mir::StatementKind::FakeRead( + fake_read_place.0.stable(tables, cx), + fake_read_place.1.stable(tables, cx), + ), mir::StatementKind::SetDiscriminant { place, variant_index } => { - stable_mir::mir::StatementKind::SetDiscriminant { + crate::mir::StatementKind::SetDiscriminant { place: place.as_ref().stable(tables, cx), variant_index: variant_index.stable(tables, cx), } } mir::StatementKind::Deinit(place) => { - stable_mir::mir::StatementKind::Deinit(place.stable(tables, cx)) + crate::mir::StatementKind::Deinit(place.stable(tables, cx)) } mir::StatementKind::StorageLive(place) => { - stable_mir::mir::StatementKind::StorageLive(place.stable(tables, cx)) + crate::mir::StatementKind::StorageLive(place.stable(tables, cx)) } mir::StatementKind::StorageDead(place) => { - stable_mir::mir::StatementKind::StorageDead(place.stable(tables, cx)) + crate::mir::StatementKind::StorageDead(place.stable(tables, cx)) + } + mir::StatementKind::Retag(retag, place) => { + crate::mir::StatementKind::Retag(retag.stable(tables, cx), place.stable(tables, cx)) } - mir::StatementKind::Retag(retag, place) => stable_mir::mir::StatementKind::Retag( - retag.stable(tables, cx), - place.stable(tables, cx), - ), mir::StatementKind::PlaceMention(place) => { - stable_mir::mir::StatementKind::PlaceMention(place.stable(tables, cx)) + crate::mir::StatementKind::PlaceMention(place.stable(tables, cx)) } mir::StatementKind::AscribeUserType(place_projection, variance) => { - stable_mir::mir::StatementKind::AscribeUserType { + crate::mir::StatementKind::AscribeUserType { place: place_projection.as_ref().0.stable(tables, cx), projections: place_projection.as_ref().1.stable(tables, cx), variance: variance.stable(tables, cx), } } mir::StatementKind::Coverage(coverage) => { - stable_mir::mir::StatementKind::Coverage(opaque(coverage)) + crate::mir::StatementKind::Coverage(opaque(coverage)) } mir::StatementKind::Intrinsic(intrinstic) => { - stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx)) - } - mir::StatementKind::ConstEvalCounter => { - stable_mir::mir::StatementKind::ConstEvalCounter + crate::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx)) } + mir::StatementKind::ConstEvalCounter => crate::mir::StatementKind::ConstEvalCounter, // BackwardIncompatibleDropHint has no semantics, so it is translated to Nop. mir::StatementKind::BackwardIncompatibleDropHint { .. } => { - stable_mir::mir::StatementKind::Nop + crate::mir::StatementKind::Nop } - mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop, + mir::StatementKind::Nop => crate::mir::StatementKind::Nop, } } } impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { - type T = stable_mir::mir::Rvalue; + type T = crate::mir::Rvalue; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -205,91 +199,89 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { ) -> Self::T { use rustc_middle::mir::Rvalue::*; match self { - Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables, cx)), + Use(op) => crate::mir::Rvalue::Use(op.stable(tables, cx)), Repeat(op, len) => { let len = len.stable(tables, cx); - stable_mir::mir::Rvalue::Repeat(op.stable(tables, cx), len) + crate::mir::Rvalue::Repeat(op.stable(tables, cx), len) } - Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( + Ref(region, kind, place) => crate::mir::Rvalue::Ref( region.stable(tables, cx), kind.stable(tables, cx), place.stable(tables, cx), ), ThreadLocalRef(def_id) => { - stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) + crate::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) } - RawPtr(mutability, place) => stable_mir::mir::Rvalue::AddressOf( + RawPtr(mutability, place) => crate::mir::Rvalue::AddressOf( mutability.stable(tables, cx), place.stable(tables, cx), ), - Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables, cx)), - Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast( + Len(place) => crate::mir::Rvalue::Len(place.stable(tables, cx)), + Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast( cast_kind.stable(tables, cx), op.stable(tables, cx), ty.stable(tables, cx), ), BinaryOp(bin_op, ops) => { if let Some(bin_op) = bin_op.overflowing_to_wrapping() { - stable_mir::mir::Rvalue::CheckedBinaryOp( + crate::mir::Rvalue::CheckedBinaryOp( bin_op.stable(tables, cx), ops.0.stable(tables, cx), ops.1.stable(tables, cx), ) } else { - stable_mir::mir::Rvalue::BinaryOp( + crate::mir::Rvalue::BinaryOp( bin_op.stable(tables, cx), ops.0.stable(tables, cx), ops.1.stable(tables, cx), ) } } - NullaryOp(null_op, ty) => stable_mir::mir::Rvalue::NullaryOp( - null_op.stable(tables, cx), - ty.stable(tables, cx), - ), + NullaryOp(null_op, ty) => { + crate::mir::Rvalue::NullaryOp(null_op.stable(tables, cx), ty.stable(tables, cx)) + } UnaryOp(un_op, op) => { - stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx)) + crate::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx)) } - Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables, cx)), + Discriminant(place) => crate::mir::Rvalue::Discriminant(place.stable(tables, cx)), Aggregate(agg_kind, operands) => { let operands = operands.iter().map(|op| op.stable(tables, cx)).collect(); - stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands) + crate::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands) } - ShallowInitBox(op, ty) => stable_mir::mir::Rvalue::ShallowInitBox( - op.stable(tables, cx), - ty.stable(tables, cx), - ), - CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables, cx)), + ShallowInitBox(op, ty) => { + crate::mir::Rvalue::ShallowInitBox(op.stable(tables, cx), ty.stable(tables, cx)) + } + CopyForDeref(place) => crate::mir::Rvalue::CopyForDeref(place.stable(tables, cx)), WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), } } } impl<'tcx> Stable<'tcx> for mir::Mutability { - type T = stable_mir::mir::Mutability; + type T = crate::mir::Mutability; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_hir::Mutability::*; match *self { - Not => stable_mir::mir::Mutability::Not, - Mut => stable_mir::mir::Mutability::Mut, + Not => crate::mir::Mutability::Not, + Mut => crate::mir::Mutability::Mut, } } } impl<'tcx> Stable<'tcx> for mir::RawPtrKind { - type T = stable_mir::mir::RawPtrKind; + type T = crate::mir::RawPtrKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use mir::RawPtrKind::*; match *self { - Const => stable_mir::mir::RawPtrKind::Const, - Mut => stable_mir::mir::RawPtrKind::Mut, - FakeForPtrMetadata => stable_mir::mir::RawPtrKind::FakeForPtrMetadata, + Const => crate::mir::RawPtrKind::Const, + Mut => crate::mir::RawPtrKind::Mut, + FakeForPtrMetadata => crate::mir::RawPtrKind::FakeForPtrMetadata, } } } impl<'tcx> Stable<'tcx> for mir::BorrowKind { - type T = stable_mir::mir::BorrowKind; + type T = crate::mir::BorrowKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -297,38 +289,38 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind { ) -> Self::T { use rustc_middle::mir::BorrowKind::*; match *self { - Shared => stable_mir::mir::BorrowKind::Shared, - Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables, cx)), - Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) }, + Shared => crate::mir::BorrowKind::Shared, + Fake(kind) => crate::mir::BorrowKind::Fake(kind.stable(tables, cx)), + Mut { kind } => crate::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) }, } } } impl<'tcx> Stable<'tcx> for mir::MutBorrowKind { - type T = stable_mir::mir::MutBorrowKind; + type T = crate::mir::MutBorrowKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::MutBorrowKind::*; match *self { - Default => stable_mir::mir::MutBorrowKind::Default, - TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow, - ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture, + Default => crate::mir::MutBorrowKind::Default, + TwoPhaseBorrow => crate::mir::MutBorrowKind::TwoPhaseBorrow, + ClosureCapture => crate::mir::MutBorrowKind::ClosureCapture, } } } impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind { - type T = stable_mir::mir::FakeBorrowKind; + type T = crate::mir::FakeBorrowKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::FakeBorrowKind::*; match *self { - Deep => stable_mir::mir::FakeBorrowKind::Deep, - Shallow => stable_mir::mir::FakeBorrowKind::Shallow, + Deep => crate::mir::FakeBorrowKind::Deep, + Shallow => crate::mir::FakeBorrowKind::Shallow, } } } impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { - type T = stable_mir::mir::NullOp; + type T = crate::mir::NullOp; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -336,19 +328,19 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { ) -> Self::T { use rustc_middle::mir::NullOp::*; match self { - SizeOf => stable_mir::mir::NullOp::SizeOf, - AlignOf => stable_mir::mir::NullOp::AlignOf, - OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( + SizeOf => crate::mir::NullOp::SizeOf, + AlignOf => crate::mir::NullOp::AlignOf, + OffsetOf(indices) => crate::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables, cx)).collect(), ), - UbChecks => stable_mir::mir::NullOp::UbChecks, - ContractChecks => stable_mir::mir::NullOp::ContractChecks, + UbChecks => crate::mir::NullOp::UbChecks, + ContractChecks => crate::mir::NullOp::ContractChecks, } } } impl<'tcx> Stable<'tcx> for mir::CastKind { - type T = stable_mir::mir::CastKind; + type T = crate::mir::CastKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -356,40 +348,38 @@ impl<'tcx> Stable<'tcx> for mir::CastKind { ) -> Self::T { use rustc_middle::mir::CastKind::*; match self { - PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress, - PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance, - PointerCoercion(c, _) => { - stable_mir::mir::CastKind::PointerCoercion(c.stable(tables, cx)) - } - IntToInt => stable_mir::mir::CastKind::IntToInt, - FloatToInt => stable_mir::mir::CastKind::FloatToInt, - FloatToFloat => stable_mir::mir::CastKind::FloatToFloat, - IntToFloat => stable_mir::mir::CastKind::IntToFloat, - PtrToPtr => stable_mir::mir::CastKind::PtrToPtr, - FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr, - Transmute => stable_mir::mir::CastKind::Transmute, + PointerExposeProvenance => crate::mir::CastKind::PointerExposeAddress, + PointerWithExposedProvenance => crate::mir::CastKind::PointerWithExposedProvenance, + PointerCoercion(c, _) => crate::mir::CastKind::PointerCoercion(c.stable(tables, cx)), + IntToInt => crate::mir::CastKind::IntToInt, + FloatToInt => crate::mir::CastKind::FloatToInt, + FloatToFloat => crate::mir::CastKind::FloatToFloat, + IntToFloat => crate::mir::CastKind::IntToFloat, + PtrToPtr => crate::mir::CastKind::PtrToPtr, + FnPtrToPtr => crate::mir::CastKind::FnPtrToPtr, + Transmute => crate::mir::CastKind::Transmute, } } } impl<'tcx> Stable<'tcx> for mir::FakeReadCause { - type T = stable_mir::mir::FakeReadCause; + type T = crate::mir::FakeReadCause; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::FakeReadCause::*; match self { - ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard, + ForMatchGuard => crate::mir::FakeReadCause::ForMatchGuard, ForMatchedPlace(local_def_id) => { - stable_mir::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id)) + crate::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id)) } - ForGuardBinding => stable_mir::mir::FakeReadCause::ForGuardBinding, - ForLet(local_def_id) => stable_mir::mir::FakeReadCause::ForLet(opaque(local_def_id)), - ForIndex => stable_mir::mir::FakeReadCause::ForIndex, + ForGuardBinding => crate::mir::FakeReadCause::ForGuardBinding, + ForLet(local_def_id) => crate::mir::FakeReadCause::ForLet(opaque(local_def_id)), + ForIndex => crate::mir::FakeReadCause::ForIndex, } } } impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { - type T = stable_mir::mir::Operand; + type T = crate::mir::Operand; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -397,22 +387,22 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { ) -> Self::T { use rustc_middle::mir::Operand::*; match self { - Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables, cx)), - Move(place) => stable_mir::mir::Operand::Move(place.stable(tables, cx)), - Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables, cx)), + Copy(place) => crate::mir::Operand::Copy(place.stable(tables, cx)), + Move(place) => crate::mir::Operand::Move(place.stable(tables, cx)), + Constant(c) => crate::mir::Operand::Constant(c.stable(tables, cx)), } } } impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> { - type T = stable_mir::mir::ConstOperand; + type T = crate::mir::ConstOperand; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::mir::ConstOperand { + crate::mir::ConstOperand { span: self.span.stable(tables, cx), user_ty: self.user_ty.map(|u| u.as_usize()).or(None), const_: self.const_.stable(tables, cx), @@ -421,13 +411,13 @@ impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> { } impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { - type T = stable_mir::mir::Place; + type T = crate::mir::Place; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::mir::Place { + crate::mir::Place { local: self.local.as_usize(), projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(), } @@ -435,7 +425,7 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { } impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> { - type T = stable_mir::mir::ProjectionElem; + type T = crate::mir::ProjectionElem; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -443,39 +433,36 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> { ) -> Self::T { use rustc_middle::mir::ProjectionElem::*; match self { - Deref => stable_mir::mir::ProjectionElem::Deref, - Field(idx, ty) => stable_mir::mir::ProjectionElem::Field( - idx.stable(tables, cx), - ty.stable(tables, cx), - ), - Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables, cx)), + Deref => crate::mir::ProjectionElem::Deref, + Field(idx, ty) => { + crate::mir::ProjectionElem::Field(idx.stable(tables, cx), ty.stable(tables, cx)) + } + Index(local) => crate::mir::ProjectionElem::Index(local.stable(tables, cx)), ConstantIndex { offset, min_length, from_end } => { - stable_mir::mir::ProjectionElem::ConstantIndex { + crate::mir::ProjectionElem::ConstantIndex { offset: *offset, min_length: *min_length, from_end: *from_end, } } - Subslice { from, to, from_end } => stable_mir::mir::ProjectionElem::Subslice { - from: *from, - to: *to, - from_end: *from_end, - }, + Subslice { from, to, from_end } => { + crate::mir::ProjectionElem::Subslice { from: *from, to: *to, from_end: *from_end } + } // MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the // variant, used for printing MIR. However this information should also be accessible // via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore // dropped when converting to Stable MIR. A brief justification for this decision can be // found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486 - Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables, cx)), - OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)), - Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables, cx)), + Downcast(_, idx) => crate::mir::ProjectionElem::Downcast(idx.stable(tables, cx)), + OpaqueCast(ty) => crate::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)), + Subtype(ty) => crate::mir::ProjectionElem::Subtype(ty.stable(tables, cx)), UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), } } } impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { - type T = stable_mir::mir::UserTypeProjection; + type T = crate::mir::UserTypeProjection; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) } @@ -483,40 +470,40 @@ impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { } impl<'tcx> Stable<'tcx> for mir::Local { - type T = stable_mir::mir::Local; + type T = crate::mir::Local; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { self.as_usize() } } impl<'tcx> Stable<'tcx> for mir::RetagKind { - type T = stable_mir::mir::RetagKind; + type T = crate::mir::RetagKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::RetagKind; match self { - RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry, - RetagKind::TwoPhase => stable_mir::mir::RetagKind::TwoPhase, - RetagKind::Raw => stable_mir::mir::RetagKind::Raw, - RetagKind::Default => stable_mir::mir::RetagKind::Default, + RetagKind::FnEntry => crate::mir::RetagKind::FnEntry, + RetagKind::TwoPhase => crate::mir::RetagKind::TwoPhase, + RetagKind::Raw => crate::mir::RetagKind::Raw, + RetagKind::Default => crate::mir::RetagKind::Default, } } } impl<'tcx> Stable<'tcx> for mir::UnwindAction { - type T = stable_mir::mir::UnwindAction; + type T = crate::mir::UnwindAction; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::UnwindAction; match self { - UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue, - UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable, - UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate, - UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()), + UnwindAction::Continue => crate::mir::UnwindAction::Continue, + UnwindAction::Unreachable => crate::mir::UnwindAction::Unreachable, + UnwindAction::Terminate(_) => crate::mir::UnwindAction::Terminate, + UnwindAction::Cleanup(bb) => crate::mir::UnwindAction::Cleanup(bb.as_usize()), } } } impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> { - type T = stable_mir::mir::NonDivergingIntrinsic; + type T = crate::mir::NonDivergingIntrinsic; fn stable<'cx>( &self, @@ -524,13 +511,14 @@ impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { use rustc_middle::mir::NonDivergingIntrinsic; - use stable_mir::mir::CopyNonOverlapping; + + use crate::mir::CopyNonOverlapping; match self { NonDivergingIntrinsic::Assume(op) => { - stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx)) + crate::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx)) } NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => { - stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + crate::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src: copy_non_overlapping.src.stable(tables, cx), dst: copy_non_overlapping.dst.stable(tables, cx), count: copy_non_overlapping.count.stable(tables, cx), @@ -541,7 +529,7 @@ impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> { } impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { - type T = stable_mir::mir::AssertMessage; + type T = crate::mir::AssertMessage; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -549,98 +537,96 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { ) -> Self::T { use rustc_middle::mir::AssertKind; match self { - AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck { + AssertKind::BoundsCheck { len, index } => crate::mir::AssertMessage::BoundsCheck { len: len.stable(tables, cx), index: index.stable(tables, cx), }, - AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow( + AssertKind::Overflow(bin_op, op1, op2) => crate::mir::AssertMessage::Overflow( bin_op.stable(tables, cx), op1.stable(tables, cx), op2.stable(tables, cx), ), AssertKind::OverflowNeg(op) => { - stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables, cx)) + crate::mir::AssertMessage::OverflowNeg(op.stable(tables, cx)) } AssertKind::DivisionByZero(op) => { - stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables, cx)) + crate::mir::AssertMessage::DivisionByZero(op.stable(tables, cx)) } AssertKind::RemainderByZero(op) => { - stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables, cx)) + crate::mir::AssertMessage::RemainderByZero(op.stable(tables, cx)) } AssertKind::ResumedAfterReturn(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx)) + crate::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx)) } AssertKind::ResumedAfterPanic(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx)) + crate::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx)) } AssertKind::ResumedAfterDrop(coroutine) => { - stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx)) + crate::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx)) } AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { + crate::mir::AssertMessage::MisalignedPointerDereference { required: required.stable(tables, cx), found: found.stable(tables, cx), } } - AssertKind::NullPointerDereference => { - stable_mir::mir::AssertMessage::NullPointerDereference - } + AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference, AssertKind::InvalidEnumConstruction(source) => { - stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) + crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) } } } } impl<'tcx> Stable<'tcx> for mir::BinOp { - type T = stable_mir::mir::BinOp; + type T = crate::mir::BinOp; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::BinOp; match self { - BinOp::Add => stable_mir::mir::BinOp::Add, - BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked, + BinOp::Add => crate::mir::BinOp::Add, + BinOp::AddUnchecked => crate::mir::BinOp::AddUnchecked, BinOp::AddWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Sub => stable_mir::mir::BinOp::Sub, - BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked, + BinOp::Sub => crate::mir::BinOp::Sub, + BinOp::SubUnchecked => crate::mir::BinOp::SubUnchecked, BinOp::SubWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Mul => stable_mir::mir::BinOp::Mul, - BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked, + BinOp::Mul => crate::mir::BinOp::Mul, + BinOp::MulUnchecked => crate::mir::BinOp::MulUnchecked, BinOp::MulWithOverflow => bug!("AddWithOverflow should have been translated already"), - BinOp::Div => stable_mir::mir::BinOp::Div, - BinOp::Rem => stable_mir::mir::BinOp::Rem, - BinOp::BitXor => stable_mir::mir::BinOp::BitXor, - BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd, - BinOp::BitOr => stable_mir::mir::BinOp::BitOr, - BinOp::Shl => stable_mir::mir::BinOp::Shl, - BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked, - BinOp::Shr => stable_mir::mir::BinOp::Shr, - BinOp::ShrUnchecked => stable_mir::mir::BinOp::ShrUnchecked, - BinOp::Eq => stable_mir::mir::BinOp::Eq, - BinOp::Lt => stable_mir::mir::BinOp::Lt, - BinOp::Le => stable_mir::mir::BinOp::Le, - BinOp::Ne => stable_mir::mir::BinOp::Ne, - BinOp::Ge => stable_mir::mir::BinOp::Ge, - BinOp::Gt => stable_mir::mir::BinOp::Gt, - BinOp::Cmp => stable_mir::mir::BinOp::Cmp, - BinOp::Offset => stable_mir::mir::BinOp::Offset, + BinOp::Div => crate::mir::BinOp::Div, + BinOp::Rem => crate::mir::BinOp::Rem, + BinOp::BitXor => crate::mir::BinOp::BitXor, + BinOp::BitAnd => crate::mir::BinOp::BitAnd, + BinOp::BitOr => crate::mir::BinOp::BitOr, + BinOp::Shl => crate::mir::BinOp::Shl, + BinOp::ShlUnchecked => crate::mir::BinOp::ShlUnchecked, + BinOp::Shr => crate::mir::BinOp::Shr, + BinOp::ShrUnchecked => crate::mir::BinOp::ShrUnchecked, + BinOp::Eq => crate::mir::BinOp::Eq, + BinOp::Lt => crate::mir::BinOp::Lt, + BinOp::Le => crate::mir::BinOp::Le, + BinOp::Ne => crate::mir::BinOp::Ne, + BinOp::Ge => crate::mir::BinOp::Ge, + BinOp::Gt => crate::mir::BinOp::Gt, + BinOp::Cmp => crate::mir::BinOp::Cmp, + BinOp::Offset => crate::mir::BinOp::Offset, } } } impl<'tcx> Stable<'tcx> for mir::UnOp { - type T = stable_mir::mir::UnOp; + type T = crate::mir::UnOp; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::mir::UnOp; match self { - UnOp::Not => stable_mir::mir::UnOp::Not, - UnOp::Neg => stable_mir::mir::UnOp::Neg, - UnOp::PtrMetadata => stable_mir::mir::UnOp::PtrMetadata, + UnOp::Not => crate::mir::UnOp::Not, + UnOp::Neg => crate::mir::UnOp::Neg, + UnOp::PtrMetadata => crate::mir::UnOp::PtrMetadata, } } } impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { - type T = stable_mir::mir::AggregateKind; + type T = crate::mir::AggregateKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -648,11 +634,11 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { ) -> Self::T { match self { mir::AggregateKind::Array(ty) => { - stable_mir::mir::AggregateKind::Array(ty.stable(tables, cx)) + crate::mir::AggregateKind::Array(ty.stable(tables, cx)) } - mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple, + mir::AggregateKind::Tuple => crate::mir::AggregateKind::Tuple, mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => { - stable_mir::mir::AggregateKind::Adt( + crate::mir::AggregateKind::Adt( tables.adt_def(*def_id), var_idx.stable(tables, cx), generic_arg.stable(tables, cx), @@ -660,26 +646,24 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { field_idx.map(|idx| idx.index()), ) } - mir::AggregateKind::Closure(def_id, generic_arg) => { - stable_mir::mir::AggregateKind::Closure( - tables.closure_def(*def_id), - generic_arg.stable(tables, cx), - ) - } + mir::AggregateKind::Closure(def_id, generic_arg) => crate::mir::AggregateKind::Closure( + tables.closure_def(*def_id), + generic_arg.stable(tables, cx), + ), mir::AggregateKind::Coroutine(def_id, generic_arg) => { - stable_mir::mir::AggregateKind::Coroutine( + crate::mir::AggregateKind::Coroutine( tables.coroutine_def(*def_id), generic_arg.stable(tables, cx), cx.coroutine_movability(*def_id).stable(tables, cx), ) } mir::AggregateKind::CoroutineClosure(def_id, generic_args) => { - stable_mir::mir::AggregateKind::CoroutineClosure( + crate::mir::AggregateKind::CoroutineClosure( tables.coroutine_closure_def(*def_id), generic_args.stable(tables, cx), ) } - mir::AggregateKind::RawPtr(ty, mutability) => stable_mir::mir::AggregateKind::RawPtr( + mir::AggregateKind::RawPtr(ty, mutability) => crate::mir::AggregateKind::RawPtr( ty.stable(tables, cx), mutability.stable(tables, cx), ), @@ -688,7 +672,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { } impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { - type T = stable_mir::mir::InlineAsmOperand; + type T = crate::mir::InlineAsmOperand; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -710,18 +694,18 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { | InlineAsmOperand::Label { .. } => (None, None), }; - stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") } + crate::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") } } } impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { - type T = stable_mir::mir::Terminator; + type T = crate::mir::Terminator; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::mir::Terminator; + use crate::mir::Terminator; Terminator { kind: self.kind.stable(tables, cx), span: self.source_info.span.stable(tables, cx), @@ -730,13 +714,13 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { } impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { - type T = stable_mir::mir::TerminatorKind; + type T = crate::mir::TerminatorKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::mir::TerminatorKind; + use crate::mir::TerminatorKind; match self { mir::TerminatorKind::Goto { target } => { TerminatorKind::Goto { target: target.as_usize() } @@ -745,7 +729,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { discr: discr.stable(tables, cx), targets: { let branches = targets.iter().map(|(val, target)| (val, target.as_usize())); - stable_mir::mir::SwitchTargets::new( + crate::mir::SwitchTargets::new( branches.collect(), targets.otherwise().as_usize(), ) @@ -830,7 +814,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> { } impl<'tcx> Stable<'tcx> for mir::interpret::Allocation { - type T = stable_mir::ty::Allocation; + type T = crate::ty::Allocation; fn stable<'cx>( &self, @@ -848,7 +832,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation { } impl<'tcx> Stable<'tcx> for mir::interpret::AllocId { - type T = stable_mir::mir::alloc::AllocId; + type T = crate::mir::alloc::AllocId; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -885,7 +869,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> { } impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { - type T = stable_mir::ty::MirConst; + type T = crate::ty::MirConst; fn stable<'cx>( &self, @@ -895,17 +879,16 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { let id = tables.intern_mir_const(cx.lift(*self).unwrap()); match *self { mir::Const::Ty(ty, c) => MirConst::new( - stable_mir::ty::ConstantKind::Ty(c.stable(tables, cx)), + crate::ty::ConstantKind::Ty(c.stable(tables, cx)), ty.stable(tables, cx), id, ), mir::Const::Unevaluated(unev_const, ty) => { - let kind = - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - def: tables.const_def(unev_const.def), - args: unev_const.args.stable(tables, cx), - promoted: unev_const.promoted.map(|u| u.as_u32()), - }); + let kind = crate::ty::ConstantKind::Unevaluated(crate::ty::UnevaluatedConst { + def: tables.const_def(unev_const.def), + args: unev_const.args.stable(tables, cx), + promoted: unev_const.promoted.map(|u| u.as_u32()), + }); let ty = ty.stable(tables, cx); MirConst::new(kind, ty, id) } @@ -933,14 +916,14 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled { } impl<'tcx> Stable<'tcx> for MonoItem<'tcx> { - type T = stable_mir::mir::mono::MonoItem; + type T = crate::mir::mono::MonoItem; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::mir::mono::MonoItem as StableMonoItem; + use crate::mir::mono::MonoItem as StableMonoItem; match self { MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)), MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)), diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs b/compiler/stable_mir/src/unstable/convert/stable/mod.rs index 799917c6e17..e7f14bbdfc8 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs +++ b/compiler/stable_mir/src/unstable/convert/stable/mod.rs @@ -3,21 +3,20 @@ use rustc_abi::FieldIdx; use rustc_smir::Tables; use rustc_smir::context::SmirCtxt; -use stable_mir::compiler_interface::BridgeTys; use super::Stable; -use crate::{rustc_smir, stable_mir}; +use crate::compiler_interface::BridgeTys; mod abi; mod mir; mod ty; impl<'tcx> Stable<'tcx> for rustc_hir::Safety { - type T = stable_mir::mir::Safety; + type T = crate::mir::Safety; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe, - rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe, + rustc_hir::Safety::Unsafe => crate::mir::Safety::Unsafe, + rustc_hir::Safety::Safe => crate::mir::Safety::Safe, } } } @@ -30,19 +29,19 @@ impl<'tcx> Stable<'tcx> for FieldIdx { } impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource { - type T = stable_mir::mir::CoroutineSource; + type T = crate::mir::CoroutineSource; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_hir::CoroutineSource; match self { - CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block, - CoroutineSource::Closure => stable_mir::mir::CoroutineSource::Closure, - CoroutineSource::Fn => stable_mir::mir::CoroutineSource::Fn, + CoroutineSource::Block => crate::mir::CoroutineSource::Block, + CoroutineSource::Closure => crate::mir::CoroutineSource::Closure, + CoroutineSource::Fn => crate::mir::CoroutineSource::Fn, } } } impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { - type T = stable_mir::mir::CoroutineKind; + type T = crate::mir::CoroutineKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -51,23 +50,23 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { use rustc_hir::{CoroutineDesugaring, CoroutineKind}; match *self { CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::Async, + crate::mir::CoroutineKind::Desugared( + crate::mir::CoroutineDesugaring::Async, source.stable(tables, cx), ) } CoroutineKind::Desugared(CoroutineDesugaring::Gen, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::Gen, + crate::mir::CoroutineKind::Desugared( + crate::mir::CoroutineDesugaring::Gen, source.stable(tables, cx), ) } CoroutineKind::Coroutine(movability) => { - stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables, cx)) + crate::mir::CoroutineKind::Coroutine(movability.stable(tables, cx)) } CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, source) => { - stable_mir::mir::CoroutineKind::Desugared( - stable_mir::mir::CoroutineDesugaring::AsyncGen, + crate::mir::CoroutineKind::Desugared( + crate::mir::CoroutineDesugaring::AsyncGen, source.stable(tables, cx), ) } @@ -76,7 +75,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind { } impl<'tcx> Stable<'tcx> for rustc_span::Symbol { - type T = stable_mir::Symbol; + type T = crate::Symbol; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { self.to_string() @@ -84,7 +83,7 @@ impl<'tcx> Stable<'tcx> for rustc_span::Symbol { } impl<'tcx> Stable<'tcx> for rustc_span::Span { - type T = stable_mir::ty::Span; + type T = crate::ty::Span; fn stable<'cx>( &self, diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs b/compiler/stable_mir/src/unstable/convert/stable/ty.rs index 596c8b96bfc..366f7ea01d4 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs +++ b/compiler/stable_mir/src/unstable/convert/stable/ty.rs @@ -4,73 +4,69 @@ use rustc_middle::ty::Ty; use rustc_middle::{bug, mir, ty}; use rustc_smir::Tables; use rustc_smir::context::SmirCtxt; -use stable_mir::alloc; -use stable_mir::compiler_interface::BridgeTys; -use stable_mir::ty::{ + +use crate::alloc; +use crate::compiler_interface::BridgeTys; +use crate::ty::{ AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy, }; -use stable_mir::unstable::Stable; - -use crate::{rustc_smir, stable_mir}; +use crate::unstable::Stable; impl<'tcx> Stable<'tcx> for ty::AliasTyKind { - type T = stable_mir::ty::AliasKind; + type T = crate::ty::AliasKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - ty::Projection => stable_mir::ty::AliasKind::Projection, - ty::Inherent => stable_mir::ty::AliasKind::Inherent, - ty::Opaque => stable_mir::ty::AliasKind::Opaque, - ty::Free => stable_mir::ty::AliasKind::Free, + ty::Projection => crate::ty::AliasKind::Projection, + ty::Inherent => crate::ty::AliasKind::Inherent, + ty::Opaque => crate::ty::AliasKind::Opaque, + ty::Free => crate::ty::AliasKind::Free, } } } impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { - type T = stable_mir::ty::AliasTy; + type T = crate::ty::AliasTy; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::AliasTy { args, def_id, .. } = self; - stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) } + crate::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { - type T = stable_mir::ty::AliasTerm; + type T = crate::ty::AliasTerm; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::AliasTerm { args, def_id, .. } = self; - stable_mir::ty::AliasTerm { - def_id: tables.alias_def(*def_id), - args: args.stable(tables, cx), - } + crate::ty::AliasTerm { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::DynKind { - type T = stable_mir::ty::DynKind; + type T = crate::ty::DynKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - ty::Dyn => stable_mir::ty::DynKind::Dyn, + ty::Dyn => crate::ty::DynKind::Dyn, } } } impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { - type T = stable_mir::ty::ExistentialPredicate; + type T = crate::ty::ExistentialPredicate; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::ExistentialPredicate::*; + use crate::ty::ExistentialPredicate::*; match self { ty::ExistentialPredicate::Trait(existential_trait_ref) => { Trait(existential_trait_ref.stable(tables, cx)) @@ -84,7 +80,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { } impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { - type T = stable_mir::ty::ExistentialTraitRef; + type T = crate::ty::ExistentialTraitRef; fn stable<'cx>( &self, @@ -92,7 +88,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::ExistentialTraitRef { def_id, args, .. } = self; - stable_mir::ty::ExistentialTraitRef { + crate::ty::ExistentialTraitRef { def_id: tables.trait_def(*def_id), generic_args: args.stable(tables, cx), } @@ -100,14 +96,14 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { } impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { - type T = stable_mir::ty::TermKind; + type T = crate::ty::TermKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::TermKind; + use crate::ty::TermKind; match self { ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables, cx)), ty::TermKind::Const(cnst) => { @@ -119,7 +115,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { } impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { - type T = stable_mir::ty::ExistentialProjection; + type T = crate::ty::ExistentialProjection; fn stable<'cx>( &self, @@ -127,7 +123,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::ExistentialProjection { def_id, args, term, .. } = self; - stable_mir::ty::ExistentialProjection { + crate::ty::ExistentialProjection { def_id: tables.trait_def(*def_id), generic_args: args.stable(tables, cx), term: term.kind().stable(tables, cx), @@ -136,7 +132,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { } impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { - type T = stable_mir::mir::PointerCoercion; + type T = crate::mir::PointerCoercion; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -144,16 +140,14 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { ) -> Self::T { use rustc_middle::ty::adjustment::PointerCoercion; match self { - PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, - PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, + PointerCoercion::ReifyFnPointer => crate::mir::PointerCoercion::ReifyFnPointer, + PointerCoercion::UnsafeFnPointer => crate::mir::PointerCoercion::UnsafeFnPointer, PointerCoercion::ClosureFnPointer(safety) => { - stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables, cx)) + crate::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables, cx)) } - PointerCoercion::MutToConstPointer => { - stable_mir::mir::PointerCoercion::MutToConstPointer - } - PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer, - PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize, + PointerCoercion::MutToConstPointer => crate::mir::PointerCoercion::MutToConstPointer, + PointerCoercion::ArrayToPointer => crate::mir::PointerCoercion::ArrayToPointer, + PointerCoercion::Unsize => crate::mir::PointerCoercion::Unsize, } } } @@ -178,14 +172,14 @@ impl<'tcx> Stable<'tcx> for ty::AdtKind { } impl<'tcx> Stable<'tcx> for ty::FieldDef { - type T = stable_mir::ty::FieldDef; + type T = crate::ty::FieldDef; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::ty::FieldDef { + crate::ty::FieldDef { def: tables.create_def_id(self.did), name: self.name.stable(tables, cx), } @@ -193,7 +187,7 @@ impl<'tcx> Stable<'tcx> for ty::FieldDef { } impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { - type T = stable_mir::ty::GenericArgs; + type T = crate::ty::GenericArgs; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -204,14 +198,14 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { } impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { - type T = stable_mir::ty::GenericArgKind; + type T = crate::ty::GenericArgKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::GenericArgKind; + use crate::ty::GenericArgKind; match self { ty::GenericArgKind::Lifetime(region) => { GenericArgKind::Lifetime(region.stable(tables, cx)) @@ -226,14 +220,14 @@ impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S> where S: Stable<'tcx, T = V>, { - type T = stable_mir::ty::Binder<V>; + type T = crate::ty::Binder<V>; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::Binder; + use crate::ty::Binder; Binder { value: self.as_ref().skip_binder().stable(tables, cx), @@ -250,27 +244,27 @@ impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<'tcx, S> where S: Stable<'tcx, T = V>, { - type T = stable_mir::ty::EarlyBinder<V>; + type T = crate::ty::EarlyBinder<V>; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::EarlyBinder; + use crate::ty::EarlyBinder; EarlyBinder { value: self.as_ref().skip_binder().stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { - type T = stable_mir::ty::FnSig; + type T = crate::ty::FnSig; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::FnSig; + use crate::ty::FnSig; FnSig { inputs_and_output: self @@ -286,14 +280,14 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { } impl<'tcx> Stable<'tcx> for ty::BoundTyKind { - type T = stable_mir::ty::BoundTyKind; + type T = crate::ty::BoundTyKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::BoundTyKind; + use crate::ty::BoundTyKind; match self { ty::BoundTyKind::Anon => BoundTyKind::Anon, @@ -305,14 +299,14 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { } impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { - type T = stable_mir::ty::BoundRegionKind; + type T = crate::ty::BoundRegionKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::BoundRegionKind; + use crate::ty::BoundRegionKind; match self { ty::BoundRegionKind::Anon => BoundRegionKind::BrAnon, @@ -327,14 +321,14 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { } impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { - type T = stable_mir::ty::BoundVariableKind; + type T = crate::ty::BoundVariableKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::BoundVariableKind; + use crate::ty::BoundVariableKind; match self { ty::BoundVariableKind::Ty(bound_ty_kind) => { @@ -392,7 +386,7 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy { } impl<'tcx> Stable<'tcx> for Ty<'tcx> { - type T = stable_mir::ty::Ty; + type T = crate::ty::Ty; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -403,7 +397,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { - type T = stable_mir::ty::TyKind; + type T = crate::ty::TyKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, @@ -488,7 +482,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { } impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { - type T = stable_mir::ty::Pattern; + type T = crate::ty::Pattern; fn stable<'cx>( &self, @@ -496,7 +490,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { match **self { - ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range { + ty::PatternKind::Range { start, end } => crate::ty::Pattern::Range { // FIXME(SMIR): update data structures to not have an Option here anymore start: Some(start.stable(tables, cx)), end: Some(end.stable(tables, cx)), @@ -508,7 +502,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { } impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { - type T = stable_mir::ty::TyConst; + type T = crate::ty::TyConst; fn stable<'cx>( &self, @@ -520,18 +514,16 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { ty::ConstKind::Value(cv) => { let const_val = cx.valtree_to_const_val(cv); if matches!(const_val, mir::ConstValue::ZeroSized) { - stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables, cx)) + crate::ty::TyConstKind::ZSTValue(cv.ty.stable(tables, cx)) } else { - stable_mir::ty::TyConstKind::Value( + crate::ty::TyConstKind::Value( cv.ty.stable(tables, cx), alloc::new_allocation(cv.ty, const_val, tables, cx), ) } } - ty::ConstKind::Param(param) => { - stable_mir::ty::TyConstKind::Param(param.stable(tables, cx)) - } - ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( + ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)), + ty::ConstKind::Unevaluated(uv) => crate::ty::TyConstKind::Unevaluated( tables.const_def(uv.def), uv.args.stable(tables, cx), ), @@ -542,42 +534,42 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { ty::ConstKind::Expr(_) => unimplemented!(), }; let id = tables.intern_ty_const(ct); - stable_mir::ty::TyConst::new(kind, id) + crate::ty::TyConst::new(kind, id) } } impl<'tcx> Stable<'tcx> for ty::ParamConst { - type T = stable_mir::ty::ParamConst; + type T = crate::ty::ParamConst; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::ParamConst; + use crate::ty::ParamConst; ParamConst { index: self.index, name: self.name.to_string() } } } impl<'tcx> Stable<'tcx> for ty::ParamTy { - type T = stable_mir::ty::ParamTy; + type T = crate::ty::ParamTy; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::ParamTy; + use crate::ty::ParamTy; ParamTy { index: self.index, name: self.name.to_string() } } } impl<'tcx> Stable<'tcx> for ty::BoundTy { - type T = stable_mir::ty::BoundTy; + type T = crate::ty::BoundTy; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::BoundTy; + use crate::ty::BoundTy; BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind { - type T = stable_mir::ty::TraitSpecializationKind; + type T = crate::ty::TraitSpecializationKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::TraitSpecializationKind; + use crate::ty::TraitSpecializationKind; match self { ty::trait_def::TraitSpecializationKind::None => TraitSpecializationKind::None, @@ -590,14 +582,14 @@ impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind { } impl<'tcx> Stable<'tcx> for ty::TraitDef { - type T = stable_mir::ty::TraitDecl; + type T = crate::ty::TraitDecl; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::opaque; - use stable_mir::ty::TraitDecl; + use crate::opaque; + use crate::ty::TraitDecl; TraitDecl { def_id: tables.trait_def(self.def_id), @@ -620,27 +612,27 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { } impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { - type T = stable_mir::ty::TraitRef; + type T = crate::ty::TraitRef; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::TraitRef; + use crate::ty::TraitRef; TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables, cx)).unwrap() } } impl<'tcx> Stable<'tcx> for ty::Generics { - type T = stable_mir::ty::Generics; + type T = crate::ty::Generics; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::Generics; + use crate::ty::Generics; let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables, cx)).collect(); let param_def_id_to_index = @@ -661,10 +653,10 @@ impl<'tcx> Stable<'tcx> for ty::Generics { } impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { - type T = stable_mir::ty::GenericParamDefKind; + type T = crate::ty::GenericParamDefKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::GenericParamDefKind; + use crate::ty::GenericParamDefKind; match self { ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Type { has_default, synthetic } => { @@ -678,7 +670,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { } impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { - type T = stable_mir::ty::GenericParamDef; + type T = crate::ty::GenericParamDef; fn stable<'cx>( &self, @@ -696,7 +688,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { } impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { - type T = stable_mir::ty::PredicateKind; + type T = crate::ty::PredicateKind; fn stable<'cx>( &self, @@ -706,25 +698,24 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { use rustc_middle::ty::PredicateKind; match self { PredicateKind::Clause(clause_kind) => { - stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables, cx)) + crate::ty::PredicateKind::Clause(clause_kind.stable(tables, cx)) } PredicateKind::DynCompatible(did) => { - stable_mir::ty::PredicateKind::DynCompatible(tables.trait_def(*did)) + crate::ty::PredicateKind::DynCompatible(tables.trait_def(*did)) } PredicateKind::Subtype(subtype_predicate) => { - stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables, cx)) + crate::ty::PredicateKind::SubType(subtype_predicate.stable(tables, cx)) } PredicateKind::Coerce(coerce_predicate) => { - stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables, cx)) + crate::ty::PredicateKind::Coerce(coerce_predicate.stable(tables, cx)) } - PredicateKind::ConstEquate(a, b) => stable_mir::ty::PredicateKind::ConstEquate( - a.stable(tables, cx), - b.stable(tables, cx), - ), - PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous, + PredicateKind::ConstEquate(a, b) => { + crate::ty::PredicateKind::ConstEquate(a.stable(tables, cx), b.stable(tables, cx)) + } + PredicateKind::Ambiguous => crate::ty::PredicateKind::Ambiguous, PredicateKind::NormalizesTo(_pred) => unimplemented!(), PredicateKind::AliasRelate(a, b, alias_relation_direction) => { - stable_mir::ty::PredicateKind::AliasRelate( + crate::ty::PredicateKind::AliasRelate( a.kind().stable(tables, cx), b.kind().stable(tables, cx), alias_relation_direction.stable(tables, cx), @@ -735,7 +726,7 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { } impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { - type T = stable_mir::ty::ClauseKind; + type T = crate::ty::ClauseKind; fn stable<'cx>( &self, @@ -745,30 +736,30 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { use rustc_middle::ty::ClauseKind; match *self { ClauseKind::Trait(trait_object) => { - stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables, cx)) + crate::ty::ClauseKind::Trait(trait_object.stable(tables, cx)) } ClauseKind::RegionOutlives(region_outlives) => { - stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables, cx)) + crate::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables, cx)) } ClauseKind::TypeOutlives(type_outlives) => { let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives; - stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate( + crate::ty::ClauseKind::TypeOutlives(crate::ty::OutlivesPredicate( a.stable(tables, cx), b.stable(tables, cx), )) } ClauseKind::Projection(projection_predicate) => { - stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables, cx)) + crate::ty::ClauseKind::Projection(projection_predicate.stable(tables, cx)) } - ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType( + ClauseKind::ConstArgHasType(const_, ty) => crate::ty::ClauseKind::ConstArgHasType( const_.stable(tables, cx), ty.stable(tables, cx), ), ClauseKind::WellFormed(term) => { - stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables, cx)) + crate::ty::ClauseKind::WellFormed(term.kind().stable(tables, cx)) } ClauseKind::ConstEvaluatable(const_) => { - stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables, cx)) + crate::ty::ClauseKind::ConstEvaluatable(const_.stable(tables, cx)) } ClauseKind::HostEffect(..) => { todo!() @@ -778,20 +769,20 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { } impl<'tcx> Stable<'tcx> for ty::ClosureKind { - type T = stable_mir::ty::ClosureKind; + type T = crate::ty::ClosureKind; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::ClosureKind::*; match self { - Fn => stable_mir::ty::ClosureKind::Fn, - FnMut => stable_mir::ty::ClosureKind::FnMut, - FnOnce => stable_mir::ty::ClosureKind::FnOnce, + Fn => crate::ty::ClosureKind::Fn, + FnMut => crate::ty::ClosureKind::FnMut, + FnOnce => crate::ty::ClosureKind::FnOnce, } } } impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { - type T = stable_mir::ty::SubtypePredicate; + type T = crate::ty::SubtypePredicate; fn stable<'cx>( &self, @@ -799,12 +790,12 @@ impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::SubtypePredicate { a, b, a_is_expected: _ } = self; - stable_mir::ty::SubtypePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } + crate::ty::SubtypePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { - type T = stable_mir::ty::CoercePredicate; + type T = crate::ty::CoercePredicate; fn stable<'cx>( &self, @@ -812,24 +803,24 @@ impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::CoercePredicate { a, b } = self; - stable_mir::ty::CoercePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } + crate::ty::CoercePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { - type T = stable_mir::ty::AliasRelationDirection; + type T = crate::ty::AliasRelationDirection; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::AliasRelationDirection::*; match self { - Equate => stable_mir::ty::AliasRelationDirection::Equate, - Subtype => stable_mir::ty::AliasRelationDirection::Subtype, + Equate => crate::ty::AliasRelationDirection::Equate, + Subtype => crate::ty::AliasRelationDirection::Subtype, } } } impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { - type T = stable_mir::ty::TraitPredicate; + type T = crate::ty::TraitPredicate; fn stable<'cx>( &self, @@ -837,7 +828,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::TraitPredicate { trait_ref, polarity } = self; - stable_mir::ty::TraitPredicate { + crate::ty::TraitPredicate { trait_ref: trait_ref.stable(tables, cx), polarity: polarity.stable(tables, cx), } @@ -848,7 +839,7 @@ impl<'tcx, T> Stable<'tcx> for ty::OutlivesPredicate<'tcx, T> where T: Stable<'tcx>, { - type T = stable_mir::ty::OutlivesPredicate<T::T, Region>; + type T = crate::ty::OutlivesPredicate<T::T, Region>; fn stable<'cx>( &self, @@ -856,12 +847,12 @@ where cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::OutlivesPredicate(a, b) = self; - stable_mir::ty::OutlivesPredicate(a.stable(tables, cx), b.stable(tables, cx)) + crate::ty::OutlivesPredicate(a.stable(tables, cx), b.stable(tables, cx)) } } impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { - type T = stable_mir::ty::ProjectionPredicate; + type T = crate::ty::ProjectionPredicate; fn stable<'cx>( &self, @@ -869,7 +860,7 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { let ty::ProjectionPredicate { projection_term, term } = self; - stable_mir::ty::ProjectionPredicate { + crate::ty::ProjectionPredicate { projection_term: projection_term.stable(tables, cx), term: term.kind().stable(tables, cx), } @@ -877,32 +868,32 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { } impl<'tcx> Stable<'tcx> for ty::ImplPolarity { - type T = stable_mir::ty::ImplPolarity; + type T = crate::ty::ImplPolarity; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::ImplPolarity::*; match self { - Positive => stable_mir::ty::ImplPolarity::Positive, - Negative => stable_mir::ty::ImplPolarity::Negative, - Reservation => stable_mir::ty::ImplPolarity::Reservation, + Positive => crate::ty::ImplPolarity::Positive, + Negative => crate::ty::ImplPolarity::Negative, + Reservation => crate::ty::ImplPolarity::Reservation, } } } impl<'tcx> Stable<'tcx> for ty::PredicatePolarity { - type T = stable_mir::ty::PredicatePolarity; + type T = crate::ty::PredicatePolarity; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::PredicatePolarity::*; match self { - Positive => stable_mir::ty::PredicatePolarity::Positive, - Negative => stable_mir::ty::PredicatePolarity::Negative, + Positive => crate::ty::PredicatePolarity::Positive, + Negative => crate::ty::PredicatePolarity::Negative, } } } impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { - type T = stable_mir::ty::Region; + type T = crate::ty::Region; fn stable<'cx>( &self, @@ -914,14 +905,14 @@ impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { } impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { - type T = stable_mir::ty::RegionKind; + type T = crate::ty::RegionKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind}; + use crate::ty::{BoundRegion, EarlyParamRegion, RegionKind}; match self { ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion { index: early_reg.index, @@ -935,15 +926,13 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { }, ), ty::ReStatic => RegionKind::ReStatic, - ty::RePlaceholder(place_holder) => { - RegionKind::RePlaceholder(stable_mir::ty::Placeholder { - universe: place_holder.universe.as_u32(), - bound: BoundRegion { - var: place_holder.bound.var.as_u32(), - kind: place_holder.bound.kind.stable(tables, cx), - }, - }) - } + ty::RePlaceholder(place_holder) => RegionKind::RePlaceholder(crate::ty::Placeholder { + universe: place_holder.universe.as_u32(), + bound: BoundRegion { + var: place_holder.bound.var.as_u32(), + kind: place_holder.bound.kind.stable(tables, cx), + }, + }), ty::ReErased => RegionKind::ReErased, _ => unreachable!("{self:?}"), } @@ -951,7 +940,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { } impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { - type T = stable_mir::mir::mono::Instance; + type T = crate::mir::mono::Instance; fn stable<'cx>( &self, @@ -960,10 +949,10 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { ) -> Self::T { let def = tables.instance_def(cx.lift(*self).unwrap()); let kind = match self.def { - ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item, - ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, + ty::InstanceKind::Item(..) => crate::mir::mono::InstanceKind::Item, + ty::InstanceKind::Intrinsic(..) => crate::mir::mono::InstanceKind::Intrinsic, ty::InstanceKind::Virtual(_def_id, idx) => { - stable_mir::mir::mono::InstanceKind::Virtual { idx } + crate::mir::mono::InstanceKind::Virtual { idx } } ty::InstanceKind::VTableShim(..) | ty::InstanceKind::ReifyShim(..) @@ -976,43 +965,42 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::FutureDropPollShim(..) | ty::InstanceKind::AsyncDropGlue(..) - | ty::InstanceKind::AsyncDropGlueCtorShim(..) => { - stable_mir::mir::mono::InstanceKind::Shim - } + | ty::InstanceKind::AsyncDropGlueCtorShim(..) => crate::mir::mono::InstanceKind::Shim, }; - stable_mir::mir::mono::Instance { def, kind } + crate::mir::mono::Instance { def, kind } } } impl<'tcx> Stable<'tcx> for ty::Variance { - type T = stable_mir::mir::Variance; + type T = crate::mir::Variance; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - ty::Bivariant => stable_mir::mir::Variance::Bivariant, - ty::Contravariant => stable_mir::mir::Variance::Contravariant, - ty::Covariant => stable_mir::mir::Variance::Covariant, - ty::Invariant => stable_mir::mir::Variance::Invariant, + ty::Bivariant => crate::mir::Variance::Bivariant, + ty::Contravariant => crate::mir::Variance::Contravariant, + ty::Covariant => crate::mir::Variance::Covariant, + ty::Invariant => crate::mir::Variance::Invariant, } } } impl<'tcx> Stable<'tcx> for ty::Movability { - type T = stable_mir::ty::Movability; + type T = crate::ty::Movability; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { - ty::Movability::Static => stable_mir::ty::Movability::Static, - ty::Movability::Movable => stable_mir::ty::Movability::Movable, + ty::Movability::Static => crate::ty::Movability::Static, + ty::Movability::Movable => crate::ty::Movability::Movable, } } } impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { - type T = stable_mir::ty::Abi; + type T = crate::ty::Abi; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_abi::ExternAbi; - use stable_mir::ty::Abi; + + use crate::ty::Abi; match *self { ExternAbi::Rust => Abi::Rust, ExternAbi::C { unwind } => Abi::C { unwind }, @@ -1046,14 +1034,14 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { } impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { - type T = stable_mir::ty::ForeignModule; + type T = crate::ty::ForeignModule; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::ty::ForeignModule { + crate::ty::ForeignModule { def_id: tables.foreign_module_def(self.def_id), abi: self.abi.stable(tables, cx), } @@ -1061,14 +1049,14 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { } impl<'tcx> Stable<'tcx> for ty::AssocKind { - type T = stable_mir::ty::AssocKind; + type T = crate::ty::AssocKind; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::{AssocKind, AssocTypeData}; + use crate::ty::{AssocKind, AssocTypeData}; match *self { ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() }, ty::AssocKind::Fn { name, has_self } => { @@ -1087,10 +1075,10 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { } impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { - type T = stable_mir::ty::AssocItemContainer; + type T = crate::ty::AssocItemContainer; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { - use stable_mir::ty::AssocItemContainer; + use crate::ty::AssocItemContainer; match self { ty::AssocItemContainer::Trait => AssocItemContainer::Trait, ty::AssocItemContainer::Impl => AssocItemContainer::Impl, @@ -1099,14 +1087,14 @@ impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { } impl<'tcx> Stable<'tcx> for ty::AssocItem { - type T = stable_mir::ty::AssocItem; + type T = crate::ty::AssocItem; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::ty::AssocItem { + crate::ty::AssocItem { def_id: tables.assoc_def(self.def_id), kind: self.kind.stable(tables, cx), container: self.container.stable(tables, cx), @@ -1116,14 +1104,14 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { } impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { - type T = stable_mir::ty::ImplTraitInTraitData; + type T = crate::ty::ImplTraitInTraitData; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, _: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - use stable_mir::ty::ImplTraitInTraitData; + use crate::ty::ImplTraitInTraitData; match self { ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { ImplTraitInTraitData::Trait { @@ -1139,13 +1127,13 @@ impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { } impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> { - type T = stable_mir::ty::Discr; + type T = crate::ty::Discr; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &SmirCtxt<'cx, BridgeTys>, ) -> Self::T { - stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables, cx) } + crate::ty::Discr { val: self.val, ty: self.ty.stable(tables, cx) } } } diff --git a/compiler/stable_mir/src/unstable/internal_cx/mod.rs b/compiler/stable_mir/src/unstable/internal_cx/mod.rs new file mode 100644 index 00000000000..6b0a06e304c --- /dev/null +++ b/compiler/stable_mir/src/unstable/internal_cx/mod.rs @@ -0,0 +1,93 @@ +//! Implementation of InternalCx. + +use rustc_middle::ty::{List, Ty, TyCtxt}; +use rustc_middle::{mir, ty}; +pub(crate) use traits::*; + +use super::InternalCx; + +pub(crate) mod traits; + +impl<'tcx, T: InternalCx<'tcx>> SmirExistentialProjection<'tcx> for T { + fn new_from_args( + &self, + def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + term: ty::Term<'tcx>, + ) -> ty::ExistentialProjection<'tcx> { + ty::ExistentialProjection::new_from_args(self.tcx(), def_id, args, term) + } +} + +impl<'tcx, T: InternalCx<'tcx>> SmirExistentialTraitRef<'tcx> for T { + fn new_from_args( + &self, + trait_def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> ty::ExistentialTraitRef<'tcx> { + ty::ExistentialTraitRef::new_from_args(self.tcx(), trait_def_id, args) + } +} + +impl<'tcx, T: InternalCx<'tcx>> SmirTraitRef<'tcx> for T { + fn new_from_args( + &self, + trait_def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> ty::TraitRef<'tcx> { + ty::TraitRef::new_from_args(self.tcx(), trait_def_id, args) + } +} + +impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { + fn tcx(self) -> TyCtxt<'tcx> { + self + } + + fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> { + TyCtxt::lift(self, value) + } + + fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>, + { + TyCtxt::mk_args_from_iter(self, iter) + } + + fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> { + TyCtxt::mk_pat(self, v) + } + + fn mk_poly_existential_predicates( + self, + eps: &[ty::PolyExistentialPredicate<'tcx>], + ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { + TyCtxt::mk_poly_existential_predicates(self, eps) + } + + fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> { + TyCtxt::mk_type_list(self, v) + } + + fn lifetimes_re_erased(self) -> ty::Region<'tcx> { + self.lifetimes.re_erased + } + + fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, + { + TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) + } + + fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> { + TyCtxt::mk_place_elems(self, v) + } + + fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx> { + self.adt_def(def_id) + } +} diff --git a/compiler/stable_mir/src/unstable/internal_cx/traits.rs b/compiler/stable_mir/src/unstable/internal_cx/traits.rs new file mode 100644 index 00000000000..da443cd78f1 --- /dev/null +++ b/compiler/stable_mir/src/unstable/internal_cx/traits.rs @@ -0,0 +1,31 @@ +//! A set of traits that define a stable interface to rustc's internals. +//! +//! These traits are primarily used to clarify the behavior of different +//! functions that share the same name across various contexts. + +use rustc_middle::ty; + +pub(crate) trait SmirExistentialProjection<'tcx> { + fn new_from_args( + &self, + def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + term: ty::Term<'tcx>, + ) -> ty::ExistentialProjection<'tcx>; +} + +pub(crate) trait SmirExistentialTraitRef<'tcx> { + fn new_from_args( + &self, + trait_def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> ty::ExistentialTraitRef<'tcx>; +} + +pub(crate) trait SmirTraitRef<'tcx> { + fn new_from_args( + &self, + trait_def_id: rustc_span::def_id::DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> ty::TraitRef<'tcx>; +} diff --git a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs b/compiler/stable_mir/src/unstable/mod.rs index 77a772019eb..51c31e212f5 100644 --- a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs +++ b/compiler/stable_mir/src/unstable/mod.rs @@ -10,104 +10,18 @@ use rustc_hir::def::DefKind; use rustc_middle::ty::{List, Ty, TyCtxt}; use rustc_middle::{mir, ty}; use rustc_smir::Tables; -use rustc_smir::context::{ - SmirCtxt, SmirExistentialProjection, SmirExistentialTraitRef, SmirTraitRef, -}; -use stable_mir::{CtorKind, ItemKind}; +use rustc_smir::context::SmirCtxt; use super::compiler_interface::BridgeTys; -use crate::{rustc_smir, stable_mir}; +use crate::{CtorKind, ItemKind}; pub(crate) mod convert; - -impl<'tcx, T: InternalCx<'tcx>> SmirExistentialProjection<'tcx> for T { - fn new_from_args( - &self, - def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - term: ty::Term<'tcx>, - ) -> ty::ExistentialProjection<'tcx> { - ty::ExistentialProjection::new_from_args(self.tcx(), def_id, args, term) - } -} - -impl<'tcx, T: InternalCx<'tcx>> SmirExistentialTraitRef<'tcx> for T { - fn new_from_args( - &self, - trait_def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx> { - ty::ExistentialTraitRef::new_from_args(self.tcx(), trait_def_id, args) - } -} - -impl<'tcx, T: InternalCx<'tcx>> SmirTraitRef<'tcx> for T { - fn new_from_args( - &self, - trait_def_id: rustc_span::def_id::DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx> { - ty::TraitRef::new_from_args(self.tcx(), trait_def_id, args) - } -} - -impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { - fn tcx(self) -> TyCtxt<'tcx> { - self - } - - fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> { - TyCtxt::lift(self, value) - } - - fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>, - { - TyCtxt::mk_args_from_iter(self, iter) - } - - fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> { - TyCtxt::mk_pat(self, v) - } - - fn mk_poly_existential_predicates( - self, - eps: &[ty::PolyExistentialPredicate<'tcx>], - ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { - TyCtxt::mk_poly_existential_predicates(self, eps) - } - - fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> { - TyCtxt::mk_type_list(self, v) - } - - fn lifetimes_re_erased(self) -> ty::Region<'tcx> { - self.lifetimes.re_erased - } - - fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output - where - I: Iterator<Item = T>, - T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, - { - TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) - } - - fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> { - TyCtxt::mk_place_elems(self, v) - } - - fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx> { - self.adt_def(def_id) - } -} +mod internal_cx; /// Trait that defines the methods that are fine to call from [`RustcInternal`]. /// /// This trait is only for [`RustcInternal`]. Any other other access to rustc's internals -/// should go through [`crate::rustc_smir::context::SmirCtxt`]. +/// should go through [`rustc_smir::context::SmirCtxt`]. pub trait InternalCx<'tcx>: Copy + Clone { fn tcx(self) -> TyCtxt<'tcx>; diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/stable_mir/src/visitor.rs index 31a53d1b19d..45e2a815470 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -1,13 +1,11 @@ use std::ops::ControlFlow; -use stable_mir::Opaque; -use stable_mir::ty::TyConst; - use super::ty::{ Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; -use crate::stable_mir; +use crate::Opaque; +use crate::ty::TyConst; pub trait Visitor: Sized { type Break; diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index d03c1969b5b..70c344e49b7 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1031,7 +1031,7 @@ impl<T, A: Allocator> LinkedList<T, A> { /// Retains only the elements specified by the predicate. /// - /// In other words, remove all elements `e` for which `f(&e)` returns false. + /// In other words, remove all elements `e` for which `f(&mut e)` returns false. /// This method operates in place, visiting each element exactly once in the /// original order, and preserves the order of the retained elements. /// @@ -1047,7 +1047,7 @@ impl<T, A: Allocator> LinkedList<T, A> { /// d.push_front(2); /// d.push_front(3); /// - /// d.retain(|&x| x % 2 == 0); + /// d.retain(|&mut x| x % 2 == 0); /// /// assert_eq!(d.pop_front(), Some(2)); /// assert_eq!(d.pop_front(), None); @@ -1075,41 +1075,6 @@ impl<T, A: Allocator> LinkedList<T, A> { #[unstable(feature = "linked_list_retain", issue = "114135")] pub fn retain<F>(&mut self, mut f: F) where - F: FnMut(&T) -> bool, - { - self.retain_mut(|elem| f(elem)); - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` for which `f(&mut e)` returns false. - /// This method operates in place, visiting each element exactly once in the - /// original order, and preserves the order of the retained elements. - /// - /// # Examples - /// - /// ``` - /// #![feature(linked_list_retain)] - /// use std::collections::LinkedList; - /// - /// let mut d = LinkedList::new(); - /// - /// d.push_front(1); - /// d.push_front(2); - /// d.push_front(3); - /// - /// d.retain_mut(|x| if *x % 2 == 0 { - /// *x += 1; - /// true - /// } else { - /// false - /// }); - /// assert_eq!(d.pop_front(), Some(3)); - /// assert_eq!(d.pop_front(), None); - /// ``` - #[unstable(feature = "linked_list_retain", issue = "114135")] - pub fn retain_mut<F>(&mut self, mut f: F) - where F: FnMut(&mut T) -> bool, { let mut cursor = self.cursor_front_mut(); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 5f69f699867..187d1ca71d9 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -156,7 +156,7 @@ use crate::vec::{self, Vec}; /// ``` /// /// Next, what should `s[i]` return? Because indexing returns a reference -/// to underlying data it could be `&u8`, `&[u8]`, or something else similar. +/// to underlying data it could be `&u8`, `&[u8]`, or something similar. /// Since we're only providing one index, `&u8` makes the most sense but that /// might not be what the user expects and can be explicitly achieved with /// [`as_bytes()`]: @@ -2875,7 +2875,8 @@ macro_rules! impl_to_string { out = String::with_capacity(SIZE); } - out.push_str(self.unsigned_abs()._fmt(&mut buf)); + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { out.push_str(self.unsigned_abs()._fmt(&mut buf)); } out } } @@ -2887,7 +2888,8 @@ macro_rules! impl_to_string { const SIZE: usize = $unsigned::MAX.ilog10() as usize + 1; let mut buf = [core::mem::MaybeUninit::<u8>::uninit(); SIZE]; - self._fmt(&mut buf).to_string() + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { self._fmt(&mut buf).to_string() } } } )* diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index a41162ecd51..fcfc7f8dd29 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -9,6 +9,7 @@ #![feature(downcast_unchecked)] #![feature(exact_size_is_empty)] #![feature(hashmap_internals)] +#![feature(int_format_into)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] #![feature(pattern)] diff --git a/library/alloctests/tests/num.rs b/library/alloctests/tests/num.rs index a169bbec8e0..589b8090096 100644 --- a/library/alloctests/tests/num.rs +++ b/library/alloctests/tests/num.rs @@ -1,15 +1,21 @@ -use std::fmt::{Debug, Display}; +use core::fmt::NumBuffer; use std::str::FromStr; -fn assert_nb<Int: ToString + FromStr + Debug + Display + Eq>(value: Int) { - let s = value.to_string(); - let s2 = format!("s: {}.", value); +macro_rules! assert_nb { + ($int:ident, $value:expr) => { + let value: $int = $value; + let s = value.to_string(); + let s2 = format!("s: {}.", value); - assert_eq!(format!("s: {s}."), s2); - let Ok(ret) = Int::from_str(&s) else { - panic!("failed to convert into to string"); + assert_eq!(format!("s: {s}."), s2); + let Ok(ret) = $int::from_str(&s) else { + panic!("failed to convert into to string"); + }; + assert_eq!(ret, value); + + let mut buffer = NumBuffer::<$int>::new(); + assert_eq!(value.format_into(&mut buffer), s.as_str()); }; - assert_eq!(ret, value); } macro_rules! uint_to_s { @@ -17,11 +23,11 @@ macro_rules! uint_to_s { $( #[test] fn $fn_name() { - assert_nb::<$int>($int::MIN); - assert_nb::<$int>($int::MAX); - assert_nb::<$int>(1); - assert_nb::<$int>($int::MIN / 2); - assert_nb::<$int>($int::MAX / 2); + assert_nb!($int, $int::MIN); + assert_nb!($int, $int::MAX); + assert_nb!($int, 1); + assert_nb!($int, $int::MIN / 2); + assert_nb!($int, $int::MAX / 2); } )+ } @@ -31,13 +37,13 @@ macro_rules! int_to_s { $( #[test] fn $fn_name() { - assert_nb::<$int>($int::MIN); - assert_nb::<$int>($int::MAX); - assert_nb::<$int>(1); - assert_nb::<$int>(0); - assert_nb::<$int>(-1); - assert_nb::<$int>($int::MIN / 2); - assert_nb::<$int>($int::MAX / 2); + assert_nb!($int, $int::MIN); + assert_nb!($int, $int::MAX); + assert_nb!($int, 1); + assert_nb!($int, 0); + assert_nb!($int, -1); + assert_nb!($int, $int::MIN / 2); + assert_nb!($int, $int::MAX / 2); } )+ } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c593737af8a..5e50eacec6e 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -15,6 +15,7 @@ mod float; #[cfg(no_fp_fmt_parse)] mod nofloat; mod num; +mod num_buffer; mod rt; #[stable(feature = "fmt_flags_align", since = "1.28.0")] @@ -33,6 +34,9 @@ pub enum Alignment { Center, } +#[unstable(feature = "int_format_into", issue = "138215")] +pub use num_buffer::{NumBuffer, NumBufferTrait}; + #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[unstable(feature = "debug_closure_helpers", issue = "117729")] diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 80f462263a5..e1381ace441 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -1,5 +1,6 @@ //! Integer and floating-point number formatting +use crate::fmt::NumBuffer; use crate::mem::MaybeUninit; use crate::num::fmt as numfmt; use crate::ops::{Div, Rem, Sub}; @@ -60,7 +61,7 @@ unsafe trait GenericRadix: Sized { let zero = T::zero(); let is_nonnegative = x >= zero; let mut buf = [MaybeUninit::<u8>::uninit(); 128]; - let mut curr = buf.len(); + let mut offset = buf.len(); let base = T::from_u8(Self::BASE); if is_nonnegative { // Accumulate each digit of the number from the least significant @@ -68,8 +69,8 @@ unsafe trait GenericRadix: Sized { loop { let n = x % base; // Get the current place value. x = x / base; // Deaccumulate the number. - curr -= 1; - buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer. + offset -= 1; + buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer. if x == zero { // No more digits left to accumulate. break; @@ -80,27 +81,17 @@ unsafe trait GenericRadix: Sized { loop { let n = zero - (x % base); // Get the current place value. x = x / base; // Deaccumulate the number. - curr -= 1; - buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer. + offset -= 1; + buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer. if x == zero { // No more digits left to accumulate. break; }; } } - // SAFETY: `curr` is initialized to `buf.len()` and is only decremented, so it can't overflow. It is - // decremented exactly once for each digit. Since u128 is the widest fixed width integer format supported, - // the maximum number of digits (bits) is 128 for base-2, so `curr` won't underflow as well. - let buf = unsafe { buf.get_unchecked(curr..) }; - // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be - // valid UTF-8 - let buf = unsafe { - str::from_utf8_unchecked(slice::from_raw_parts( - MaybeUninit::slice_as_ptr(buf), - buf.len(), - )) - }; - f.pad_integral(is_nonnegative, Self::PREFIX, buf) + // SAFETY: Starting from `offset`, all elements of the slice have been set. + let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) }; + f.pad_integral(is_nonnegative, Self::PREFIX, buf_slice) } } @@ -199,6 +190,20 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; +/// This function converts a slice of ascii characters into a `&str` starting from `offset`. +/// +/// # Safety +/// +/// `buf` content starting from `offset` index MUST BE initialized and MUST BE ascii +/// characters. +unsafe fn slice_buffer_to_str(buf: &[MaybeUninit<u8>], offset: usize) -> &str { + // SAFETY: `offset` is always included between 0 and `buf`'s length. + let written = unsafe { buf.get_unchecked(offset..) }; + // SAFETY: (`assume_init_ref`) All buf content since offset is set. + // SAFETY: (`from_utf8_unchecked`) Writes use ASCII from the lookup table exclusively. + unsafe { str::from_utf8_unchecked(written.assume_init_ref()) } +} + macro_rules! impl_Display { ($($signed:ident, $unsigned:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => { @@ -212,7 +217,8 @@ macro_rules! impl_Display { // Buffer decimals for $unsigned with right alignment. let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N]; - f.pad_integral(true, "", self._fmt(&mut buf)) + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) } } #[cfg(feature = "optimize_for_size")] { @@ -230,7 +236,8 @@ macro_rules! impl_Display { // Buffer decimals for $unsigned with right alignment. let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N]; - f.pad_integral(*self >= 0, "", self.unsigned_abs()._fmt(&mut buf)) + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { f.pad_integral(*self >= 0, "", self.unsigned_abs()._fmt(&mut buf)) } } #[cfg(feature = "optimize_for_size")] { @@ -247,7 +254,14 @@ macro_rules! impl_Display { reason = "specialized method meant to only be used by `SpecToString` implementation", issue = "none" )] - pub fn _fmt<'a>(self, buf: &'a mut [MaybeUninit::<u8>]) -> &'a str { + pub unsafe fn _fmt<'a>(self, buf: &'a mut [MaybeUninit::<u8>]) -> &'a str { + // SAFETY: `buf` will always be big enough to contain all digits. + let offset = unsafe { self._fmt_inner(buf) }; + // SAFETY: Starting from `offset`, all elements of the slice have been set. + unsafe { slice_buffer_to_str(buf, offset) } + } + + unsafe fn _fmt_inner(self, buf: &mut [MaybeUninit::<u8>]) -> usize { // Count the number of bytes in buf that are not initialized. let mut offset = buf.len(); // Consume the least-significant decimals from a working copy. @@ -309,47 +323,123 @@ macro_rules! impl_Display { // not used: remain = 0; } - // SAFETY: All buf content since offset is set. - let written = unsafe { buf.get_unchecked(offset..) }; - // SAFETY: Writes use ASCII from the lookup table exclusively. + offset + } + } + + impl $signed { + /// Allows users to write an integer (in signed decimal format) into a variable `buf` of + /// type [`NumBuffer`] that is passed by the caller by mutable reference. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_format_into)] + /// use core::fmt::NumBuffer; + /// + #[doc = concat!("let n = 0", stringify!($signed), ";")] + /// let mut buf = NumBuffer::new(); + /// assert_eq!(n.format_into(&mut buf), "0"); + /// + #[doc = concat!("let n1 = 32", stringify!($signed), ";")] + /// assert_eq!(n1.format_into(&mut buf), "32"); + /// + #[doc = concat!("let n2 = ", stringify!($signed::MAX), ";")] + #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($signed::MAX), ".to_string());")] + /// ``` + #[unstable(feature = "int_format_into", issue = "138215")] + pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { + let mut offset; + + #[cfg(not(feature = "optimize_for_size"))] + // SAFETY: `buf` will always be big enough to contain all digits. unsafe { - str::from_utf8_unchecked(slice::from_raw_parts( - MaybeUninit::slice_as_ptr(written), - written.len(), - )) + offset = self.unsigned_abs()._fmt_inner(&mut buf.buf); } + #[cfg(feature = "optimize_for_size")] + { + offset = _inner_slow_integer_to_str(self.unsigned_abs().$conv_fn(), &mut buf.buf); + } + // Only difference between signed and unsigned are these 4 lines. + if self < 0 { + offset -= 1; + buf.buf[offset].write(b'-'); + } + // SAFETY: Starting from `offset`, all elements of the slice have been set. + unsafe { slice_buffer_to_str(&buf.buf, offset) } } - })* + } + + impl $unsigned { + /// Allows users to write an integer (in signed decimal format) into a variable `buf` of + /// type [`NumBuffer`] that is passed by the caller by mutable reference. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_format_into)] + /// use core::fmt::NumBuffer; + /// + #[doc = concat!("let n = 0", stringify!($unsigned), ";")] + /// let mut buf = NumBuffer::new(); + /// assert_eq!(n.format_into(&mut buf), "0"); + /// + #[doc = concat!("let n1 = 32", stringify!($unsigned), ";")] + /// assert_eq!(n1.format_into(&mut buf), "32"); + /// + #[doc = concat!("let n2 = ", stringify!($unsigned::MAX), ";")] + #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($unsigned::MAX), ".to_string());")] + /// ``` + #[unstable(feature = "int_format_into", issue = "138215")] + pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { + let offset; + + #[cfg(not(feature = "optimize_for_size"))] + // SAFETY: `buf` will always be big enough to contain all digits. + unsafe { + offset = self._fmt_inner(&mut buf.buf); + } + #[cfg(feature = "optimize_for_size")] + { + offset = _inner_slow_integer_to_str(self.$conv_fn(), &mut buf.buf); + } + // SAFETY: Starting from `offset`, all elements of the slice have been set. + unsafe { slice_buffer_to_str(&buf.buf, offset) } + } + } + + + )* #[cfg(feature = "optimize_for_size")] - fn $gen_name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { - const MAX_DEC_N: usize = $u::MAX.ilog10() as usize + 1; - let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N]; - let mut curr = MAX_DEC_N; - let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + fn _inner_slow_integer_to_str(mut n: $u, buf: &mut [MaybeUninit::<u8>]) -> usize { + let mut curr = buf.len(); // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at // each step this is kept the same as `n` is divided. Since `n` is always // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` // is safe to access. - unsafe { - loop { - curr -= 1; - buf_ptr.add(curr).write((n % 10) as u8 + b'0'); - n /= 10; + loop { + curr -= 1; + buf[curr].write((n % 10) as u8 + b'0'); + n /= 10; - if n == 0 { - break; - } + if n == 0 { + break; } } + curr + } - // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid UTF-8 - let buf_slice = unsafe { - str::from_utf8_unchecked( - slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) - }; + #[cfg(feature = "optimize_for_size")] + fn $gen_name(n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const MAX_DEC_N: usize = $u::MAX.ilog(10) as usize + 1; + let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N]; + + let offset = _inner_slow_integer_to_str(n, &mut buf); + // SAFETY: Starting from `offset`, all elements of the slice have been set. + let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) }; f.pad_integral(is_nonnegative, "", buf_slice) } }; @@ -572,7 +662,8 @@ impl fmt::Display for u128 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut buf = [MaybeUninit::<u8>::uninit(); U128_MAX_DEC_N]; - f.pad_integral(true, "", self._fmt(&mut buf)) + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) } } } @@ -584,7 +675,8 @@ impl fmt::Display for i128 { let mut buf = [MaybeUninit::<u8>::uninit(); U128_MAX_DEC_N]; let is_nonnegative = *self >= 0; - f.pad_integral(is_nonnegative, "", self.unsigned_abs()._fmt(&mut buf)) + // SAFETY: `buf` is always big enough to contain all the digits. + unsafe { f.pad_integral(is_nonnegative, "", self.unsigned_abs()._fmt(&mut buf)) } } } @@ -597,13 +689,21 @@ impl u128 { reason = "specialized method meant to only be used by `SpecToString` implementation", issue = "none" )] - pub fn _fmt<'a>(self, buf: &'a mut [MaybeUninit<u8>]) -> &'a str { + pub unsafe fn _fmt<'a>(self, buf: &'a mut [MaybeUninit<u8>]) -> &'a str { + // SAFETY: `buf` will always be big enough to contain all digits. + let offset = unsafe { self._fmt_inner(buf) }; + // SAFETY: Starting from `offset`, all elements of the slice have been set. + unsafe { slice_buffer_to_str(buf, offset) } + } + + unsafe fn _fmt_inner(self, buf: &mut [MaybeUninit<u8>]) -> usize { // Optimize common-case zero, which would also need special treatment due to // its "leading" zero. if self == 0 { - return "0"; + let offset = buf.len() - 1; + buf[offset].write(b'0'); + return offset; } - // Take the 16 least-significant decimals. let (quot_1e16, mod_1e16) = div_rem_1e16(self); let (mut remain, mut offset) = if quot_1e16 == 0 { @@ -677,16 +777,86 @@ impl u128 { buf[offset].write(DEC_DIGITS_LUT[last * 2 + 1]); // not used: remain = 0; } + offset + } + + /// Allows users to write an integer (in signed decimal format) into a variable `buf` of + /// type [`NumBuffer`] that is passed by the caller by mutable reference. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_format_into)] + /// use core::fmt::NumBuffer; + /// + /// let n = 0u128; + /// let mut buf = NumBuffer::new(); + /// assert_eq!(n.format_into(&mut buf), "0"); + /// + /// let n1 = 32u128; + /// let mut buf1 = NumBuffer::new(); + /// assert_eq!(n1.format_into(&mut buf1), "32"); + /// + /// let n2 = u128::MAX; + /// let mut buf2 = NumBuffer::new(); + /// assert_eq!(n2.format_into(&mut buf2), u128::MAX.to_string()); + /// ``` + #[unstable(feature = "int_format_into", issue = "138215")] + pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { + let diff = buf.capacity() - U128_MAX_DEC_N; + // FIXME: Once const generics are better, use `NumberBufferTrait::BUF_SIZE` as generic const + // for `fmt_u128_inner`. + // + // In the meantime, we have to use a slice starting at index 1 and add 1 to the returned + // offset to ensure the number is correctly generated at the end of the buffer. + // SAFETY: `diff` will always be between 0 and its initial value. + unsafe { self._fmt(buf.buf.get_unchecked_mut(diff..)) } + } +} - // SAFETY: All buf content since offset is set. - let written = unsafe { buf.get_unchecked(offset..) }; - // SAFETY: Writes use ASCII from the lookup table exclusively. - unsafe { - str::from_utf8_unchecked(slice::from_raw_parts( - MaybeUninit::slice_as_ptr(written), - written.len(), - )) +impl i128 { + /// Allows users to write an integer (in signed decimal format) into a variable `buf` of + /// type [`NumBuffer`] that is passed by the caller by mutable reference. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_format_into)] + /// use core::fmt::NumBuffer; + /// + /// let n = 0i128; + /// let mut buf = NumBuffer::new(); + /// assert_eq!(n.format_into(&mut buf), "0"); + /// + /// let n1 = i128::MIN; + /// assert_eq!(n1.format_into(&mut buf), i128::MIN.to_string()); + /// + /// let n2 = i128::MAX; + /// assert_eq!(n2.format_into(&mut buf), i128::MAX.to_string()); + /// ``` + #[unstable(feature = "int_format_into", issue = "138215")] + pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str { + let diff = buf.capacity() - U128_MAX_DEC_N; + // FIXME: Once const generics are better, use `NumberBufferTrait::BUF_SIZE` as generic const + // for `fmt_u128_inner`. + // + // In the meantime, we have to use a slice starting at index 1 and add 1 to the returned + // offset to ensure the number is correctly generated at the end of the buffer. + let mut offset = + // SAFETY: `buf` will always be big enough to contain all digits. + unsafe { self.unsigned_abs()._fmt_inner(buf.buf.get_unchecked_mut(diff..)) }; + // We put back the offset at the right position. + offset += diff; + // Only difference between signed and unsigned are these 4 lines. + if self < 0 { + offset -= 1; + // SAFETY: `buf` will always be big enough to contain all digits plus the minus sign. + unsafe { + buf.buf.get_unchecked_mut(offset).write(b'-'); + } } + // SAFETY: Starting from `offset`, all elements of the slice have been set. + unsafe { slice_buffer_to_str(&buf.buf, offset) } } } diff --git a/library/core/src/fmt/num_buffer.rs b/library/core/src/fmt/num_buffer.rs new file mode 100644 index 00000000000..474a8d20ef6 --- /dev/null +++ b/library/core/src/fmt/num_buffer.rs @@ -0,0 +1,60 @@ +use crate::mem::MaybeUninit; + +/// Trait used to describe the maximum number of digits in decimal base of the implemented integer. +#[unstable(feature = "int_format_into", issue = "138215")] +pub trait NumBufferTrait { + /// Maximum number of digits in decimal base of the implemented integer. + const BUF_SIZE: usize; +} + +macro_rules! impl_NumBufferTrait { + ($($signed:ident, $unsigned:ident,)*) => { + $( + #[unstable(feature = "int_format_into", issue = "138215")] + impl NumBufferTrait for $signed { + // `+ 2` and not `+ 1` to include the `-` character. + const BUF_SIZE: usize = $signed::MAX.ilog(10) as usize + 2; + } + #[unstable(feature = "int_format_into", issue = "138215")] + impl NumBufferTrait for $unsigned { + const BUF_SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1; + } + )* + } +} + +impl_NumBufferTrait! { + i8, u8, + i16, u16, + i32, u32, + i64, u64, + isize, usize, + i128, u128, +} + +/// A buffer wrapper of which the internal size is based on the maximum +/// number of digits the associated integer can have. +#[unstable(feature = "int_format_into", issue = "138215")] +#[derive(Debug)] +pub struct NumBuffer<T: NumBufferTrait> { + // FIXME: Once const generics feature is working, use `T::BUF_SIZE` instead of 40. + pub(crate) buf: [MaybeUninit<u8>; 40], + // FIXME: Remove this field once we can actually use `T`. + phantom: core::marker::PhantomData<T>, +} + +#[unstable(feature = "int_format_into", issue = "138215")] +impl<T: NumBufferTrait> NumBuffer<T> { + /// Initializes internal buffer. + #[unstable(feature = "int_format_into", issue = "138215")] + pub const fn new() -> Self { + // FIXME: Once const generics feature is working, use `T::BUF_SIZE` instead of 40. + NumBuffer { buf: [MaybeUninit::<u8>::uninit(); 40], phantom: core::marker::PhantomData } + } + + /// Returns the length of the internal buffer. + #[unstable(feature = "int_format_into", issue = "138215")] + pub const fn capacity(&self) -> usize { + self.buf.len() + } +} diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0fa066c8f7e..11d50e0f89f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -111,6 +111,15 @@ impl_zeroable_primitive!( /// ``` /// /// [null pointer optimization]: crate::option#representation +/// +/// # Note on generic usage +/// +/// `NonZero<T>` can only be used with some standard library primitive types +/// (such as `u8`, `i32`, and etc.). The type parameter `T` must implement the +/// internal trait [`ZeroablePrimitive`], which is currently permanently unstable +/// and cannot be implemented by users. Therefore, you cannot use `NonZero<T>` +/// with your own types, nor can you implement traits for all `NonZero<T>`, +/// only for concrete types. #[stable(feature = "generic_nonzero", since = "1.79.0")] #[repr(transparent)] #[rustc_nonnull_optimization_guaranteed] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 9cadbd47ab6..ab6823249c3 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -786,12 +786,12 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(mixed_integer_ops_unsigned_sub)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(2), None);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(-2), Some(3));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_sub_signed(-4), None);")] /// ``` - #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1933,12 +1933,12 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(mixed_integer_ops_unsigned_sub)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(2), 0);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(-2), 3);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_sub_signed(-4), ", stringify!($SelfT), "::MAX);")] /// ``` - #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2081,12 +2081,12 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(mixed_integer_ops_unsigned_sub)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(2), ", stringify!($SelfT), "::MAX);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(-2), 3);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_sub_signed(-4), 1);")] /// ``` - #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2540,12 +2540,12 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(mixed_integer_ops_unsigned_sub)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(2), (", stringify!($SelfT), "::MAX, true));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(-2), (3, false));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_sub_signed(-4), (1, true));")] /// ``` - #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")] + #[stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "mixed_integer_ops_unsigned_sub", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f55bdfeb354..2c77c55745b 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -304,14 +304,12 @@ mod prim_bool {} /// This is what is known as "never type fallback". /// /// Historically, the fallback type was [`()`], causing confusing behavior where `!` spontaneously -/// coerced to `()`, even when it would not infer `()` without the fallback. There are plans to -/// change it in the [2024 edition] (and possibly in all editions on a later date); see -/// [Tracking Issue for making `!` fall back to `!`][fallback-ti]. +/// coerced to `()`, even when it would not infer `()` without the fallback. The fallback was changed +/// to `!` in the [2024 edition], and will be changed in all editions at a later date. /// /// [coercion site]: <https://doc.rust-lang.org/reference/type-coercions.html#coercion-sites> /// [`()`]: prim@unit -/// [fallback-ti]: <https://github.com/rust-lang/rust/issues/123748> -/// [2024 edition]: <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html> +/// [2024 edition]: <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> /// #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 8a6925a0e9a..fe64132ff22 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -446,7 +446,7 @@ impl str { #[unstable(feature = "round_char_boundary", issue = "93743")] #[inline] pub fn ceil_char_boundary(&self, index: usize) -> usize { - if index > self.len() { + if index >= self.len() { self.len() } else { let upper_bound = Ord::min(index + 4, self.len()); diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 0ce20a143df..d9c34d4fa04 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1244,7 +1244,7 @@ impl PathBuf { /// /// The caller has free choice over the returned lifetime, including 'static. /// Indeed, this function is ideally used for data that lives for the remainder of - /// the program’s life, as dropping the returned reference will cause a memory leak. + /// the program's life, as dropping the returned reference will cause a memory leak. /// /// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include /// unused capacity that is not part of the returned slice. If you want to discard excess @@ -3028,7 +3028,7 @@ impl Path { /// /// This function always resolves `..` to the "lexical" parent. /// That is "a/b/../c" will always resolve to `a/c` which can change the meaning of the path. - /// In particular, `a/c` and `a/b/../c` are distinct on many systems because `b` may be a symbolic link, so its parent isn’t `a`. + /// In particular, `a/c` and `a/b/../c` are distinct on many systems because `b` may be a symbolic link, so its parent isn't `a`. /// /// </div> /// diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 8712332dd27..673033034ef 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -187,7 +187,7 @@ use crate::time::{Duration, Instant}; /// sender.send(expensive_computation()).unwrap(); /// }); /// -/// // Do some useful work for awhile +/// // Do some useful work for a while /// /// // Let's see what that answer was /// println!("{:?}", receiver.recv().unwrap()); diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index f942937c14d..41d1dd3ce67 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -509,7 +509,7 @@ pub enum TrySendError<T> { /// sender.send(expensive_computation()).unwrap(); /// }); /// -/// // Do some useful work for awhile +/// // Do some useful work for a while /// /// // Let's see what that answer was /// println!("{:?}", receiver.recv().unwrap()); diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index bb68a824fc3..9bc5a16b800 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -4,7 +4,7 @@ use super::hermit_abi; use crate::ffi::CStr; use crate::mem::ManuallyDrop; use crate::num::NonZero; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{io, ptr}; pub type Tid = hermit_abi::Tid; @@ -86,6 +86,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { unsafe { let _ = hermit_abi::join(self.tid); diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs index a974f4f17ae..813e1cbcd58 100644 --- a/library/std/src/sys/pal/itron/thread.rs +++ b/library/std/src/sys/pal/itron/thread.rs @@ -10,7 +10,7 @@ use crate::mem::ManuallyDrop; use crate::num::NonZero; use crate::ptr::NonNull; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{hint, io}; pub struct Thread { @@ -205,6 +205,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { // Safety: `ThreadInner` is alive at this point let inner = unsafe { self.p_inner.as_ref() }; diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 219ef1b7a98..85f6dcd96b4 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -5,7 +5,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::num::NonZero; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub struct Thread(task_queue::JoinHandle); @@ -132,6 +132,14 @@ impl Thread { usercalls::wait_timeout(0, dur, || true); } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { self.0.wait(); } diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs index e3b4908f858..b9cdc7a2a58 100644 --- a/library/std/src/sys/pal/teeos/thread.rs +++ b/library/std/src/sys/pal/teeos/thread.rs @@ -2,7 +2,7 @@ use crate::ffi::CStr; use crate::mem::{self, ManuallyDrop}; use crate::num::NonZero; use crate::sys::os; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{cmp, io, ptr}; pub const DEFAULT_MIN_STACK_SIZE: usize = 8 * 1024; @@ -109,6 +109,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + /// must join, because no pthread_detach supported pub fn join(self) { let id = self.into_id(); diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs index 7d4006ff4b2..e4776ec42fb 100644 --- a/library/std/src/sys/pal/uefi/thread.rs +++ b/library/std/src/sys/pal/uefi/thread.rs @@ -3,7 +3,7 @@ use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::ptr::NonNull; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub struct Thread(!); @@ -39,6 +39,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { self.0 } diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index d8b189413f4..53f0d1eeda5 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -6,7 +6,7 @@ use crate::sys::weak::dlsym; #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))] use crate::sys::weak::weak; use crate::sys::{os, stack_overflow}; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{cmp, io, ptr}; #[cfg(not(any( target_os = "l4re", @@ -296,6 +296,76 @@ impl Thread { } } + // Any unix that has clock_nanosleep + // If this list changes update the MIRI chock_nanosleep shim + #[cfg(any( + target_os = "freebsd", + target_os = "netbsd", + target_os = "linux", + target_os = "android", + target_os = "solaris", + target_os = "illumos", + target_os = "dragonfly", + target_os = "hurd", + target_os = "fuchsia", + target_os = "vxworks", + ))] + pub fn sleep_until(deadline: Instant) { + let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else { + // The deadline is further in the future then can be passed to + // clock_nanosleep. We have to use Self::sleep instead. This might + // happen on 32 bit platforms, especially closer to 2038. + let now = Instant::now(); + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + return; + }; + + unsafe { + // When we get interrupted (res = EINTR) call clock_nanosleep again + loop { + let res = libc::clock_nanosleep( + super::time::Instant::CLOCK_ID, + libc::TIMER_ABSTIME, + &ts, + core::ptr::null_mut(), // not required with TIMER_ABSTIME + ); + + if res == 0 { + break; + } else { + assert_eq!( + res, + libc::EINTR, + "timespec is in range, + clockid is valid and kernel should support it" + ); + } + } + } + } + + // Any unix that does not have clock_nanosleep + #[cfg(not(any( + target_os = "freebsd", + target_os = "netbsd", + target_os = "linux", + target_os = "android", + target_os = "solaris", + target_os = "illumos", + target_os = "dragonfly", + target_os = "hurd", + target_os = "fuchsia", + target_os = "vxworks", + )))] + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { let id = self.into_id(); let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index 0074d767474..bd7f74fea6a 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -261,6 +261,10 @@ pub struct Instant { } impl Instant { + #[cfg(target_vendor = "apple")] + pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_UPTIME_RAW; + #[cfg(not(target_vendor = "apple"))] + pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_MONOTONIC; pub fn now() -> Instant { // https://www.manpagez.com/man/3/clock_gettime/ // @@ -273,11 +277,7 @@ impl Instant { // // Instant on macos was historically implemented using mach_absolute_time; // we preserve this value domain out of an abundance of caution. - #[cfg(target_vendor = "apple")] - const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW; - #[cfg(not(target_vendor = "apple"))] - const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC; - Instant { t: Timespec::now(clock_id) } + Instant { t: Timespec::now(Self::CLOCK_ID) } } pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { @@ -291,6 +291,14 @@ impl Instant { pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { Some(Instant { t: self.t.checked_sub_duration(other)? }) } + + #[cfg_attr( + not(target_os = "linux"), + allow(unused, reason = "needed by the `sleep_until` on some unix platforms") + )] + pub(crate) fn into_timespec(self) -> Timespec { + self.t + } } impl fmt::Debug for Instant { diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs index 89f8bad7026..8a3119fa292 100644 --- a/library/std/src/sys/pal/unsupported/thread.rs +++ b/library/std/src/sys/pal/unsupported/thread.rs @@ -2,7 +2,7 @@ use super::unsupported; use crate::ffi::CStr; use crate::io; use crate::num::NonZero; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub struct Thread(!); @@ -26,6 +26,10 @@ impl Thread { panic!("can't sleep"); } + pub fn sleep_until(_deadline: Instant) { + panic!("can't sleep"); + } + pub fn join(self) { self.0 } diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index cc569bb3daf..5f21a553673 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -2,7 +2,7 @@ use crate::ffi::CStr; use crate::num::NonZero; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{io, mem}; cfg_if::cfg_if! { @@ -171,6 +171,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index dd5aff391fd..44ce3eab109 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -2,7 +2,7 @@ use crate::ffi::CStr; use crate::io; use crate::num::NonZero; use crate::sys::unsupported; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub struct Thread(!); @@ -41,6 +41,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) {} } diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs index 45e52cf4d04..14785171755 100644 --- a/library/std/src/sys/pal/windows/thread.rs +++ b/library/std/src/sys/pal/windows/thread.rs @@ -8,7 +8,7 @@ use crate::os::windows::io::{AsRawHandle, HandleOrNull}; use crate::sys::handle::Handle; use crate::sys::{c, stack_overflow}; use crate::sys_common::FromInner; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{io, ptr}; pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -106,6 +106,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn handle(&self) -> &Handle { &self.handle } diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs index 0ebb46dc19f..1b344e984dc 100644 --- a/library/std/src/sys/pal/xous/thread.rs +++ b/library/std/src/sys/pal/xous/thread.rs @@ -8,7 +8,7 @@ use crate::os::xous::ffi::{ map_memory, update_memory_flags, }; use crate::os::xous::services::{TicktimerScalar, ticktimer_server}; -use crate::time::Duration; +use crate::time::{Duration, Instant}; pub struct Thread { tid: ThreadId, @@ -128,6 +128,14 @@ impl Thread { } } + pub fn sleep_until(deadline: Instant) { + let now = Instant::now(); + + if let Some(delay) = deadline.checked_duration_since(now) { + Self::sleep(delay); + } + } + pub fn join(self) { join_thread(self.tid).unwrap(); } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 26b2fb44724..6075173db47 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -897,8 +897,31 @@ pub fn sleep(dur: Duration) { /// /// # Platform-specific behavior /// -/// This function uses [`sleep`] internally, see its platform-specific behavior. +/// In most cases this function will call an OS specific function. Where that +/// is not supported [`sleep`] is used. Those platforms are referred to as other +/// in the table below. /// +/// # Underlying System calls +/// +/// The following system calls are [currently] being used: +/// +/// | Platform | System call | +/// |-----------|----------------------------------------------------------------------| +/// | Linux | [clock_nanosleep] (Monotonic clock) | +/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | +/// | Android | [clock_nanosleep] (Monotonic Clock)] | +/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | +/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | +/// | Dragonfly | [clock_nanosleep] (Monotonic Clock)] | +/// | Hurd | [clock_nanosleep] (Monotonic Clock)] | +/// | Fuchsia | [clock_nanosleep] (Monotonic Clock)] | +/// | Vxworks | [clock_nanosleep] (Monotonic Clock)] | +/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | +/// +/// [currently]: crate::io#platform-specific-behavior +/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep +/// +/// **Disclaimer:** These system calls might change over time. /// /// # Examples /// @@ -923,9 +946,9 @@ pub fn sleep(dur: Duration) { /// } /// ``` /// -/// A slow api we must not call too fast and which takes a few +/// A slow API we must not call too fast and which takes a few /// tries before succeeding. By using `sleep_until` the time the -/// api call takes does not influence when we retry or when we give up +/// API call takes does not influence when we retry or when we give up /// /// ```no_run /// #![feature(thread_sleep_until)] @@ -960,11 +983,7 @@ pub fn sleep(dur: Duration) { /// ``` #[unstable(feature = "thread_sleep_until", issue = "113752")] pub fn sleep_until(deadline: Instant) { - let now = Instant::now(); - - if let Some(delay) = deadline.checked_duration_since(now) { - sleep(delay); - } + imp::Thread::sleep_until(deadline) } /// Used to ensure that `park` and `park_timeout` do not unwind, as that can diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 393426be087..cd0683f44c9 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -407,6 +407,15 @@ impl Instant { pub fn checked_sub(&self, duration: Duration) -> Option<Instant> { self.0.checked_sub_duration(&duration).map(Instant) } + + // Used by platform specific `sleep_until` implementations such as the one used on Linux. + #[cfg_attr( + not(target_os = "linux"), + allow(unused, reason = "not every platform has a specific `sleep_until`") + )] + pub(crate) fn into_inner(self) -> time::Instant { + self.0 + } } #[stable(feature = "time2", since = "1.8.0")] diff --git a/library/std/tests/thread.rs b/library/std/tests/thread.rs index 1bb17d149fa..32561dd6ab6 100644 --- a/library/std/tests/thread.rs +++ b/library/std/tests/thread.rs @@ -1,7 +1,8 @@ +#![feature(thread_sleep_until)] use std::cell::{Cell, RefCell}; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads @@ -18,6 +19,17 @@ fn sleep_very_long() { } #[test] +fn sleep_until() { + let now = Instant::now(); + let period = Duration::from_millis(100); + let deadline = now + period; + thread::sleep_until(deadline); + + let elapsed = now.elapsed(); + assert!(elapsed >= period); +} + +#[test] fn thread_local_containing_const_statements() { // This exercises the `const $init:block` cases of the thread_local macro. // Despite overlapping with expression syntax, the `const { ... }` is not diff --git a/src/bootstrap/defaults/bootstrap.library.toml b/src/bootstrap/defaults/bootstrap.library.toml index 6a867093b78..3f811402b26 100644 --- a/src/bootstrap/defaults/bootstrap.library.toml +++ b/src/bootstrap/defaults/bootstrap.library.toml @@ -1,7 +1,6 @@ # These defaults are meant for contributors to the standard library and documentation. [build] bench-stage = 1 -check-stage = 1 test-stage = 1 [rust] @@ -13,7 +12,8 @@ lto = "off" # # If compiler-affecting directories are not modified, use precompiled rustc to speed up # library development by skipping compiler builds. -download-rustc = "if-unchanged" +# FIXME: download-rustc is currently broken: https://github.com/rust-lang/rust/issues/142505 +download-rustc = false [llvm] # Will download LLVM from CI if available on your platform. diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 6c5f70b2f43..0497bae86a1 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -3,16 +3,19 @@ use crate::core::build_steps::compile::{ add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make, }; +use crate::core::build_steps::tool; use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo}; use crate::core::builder::{ self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, }; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{self, BuildStamp}; -use crate::{Mode, Subcommand}; +use crate::{Compiler, Mode, Subcommand}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Std { + /// Compiler that will check this std. + pub build_compiler: Compiler, pub target: TargetSelection, /// Whether to build only a subset of crates. /// @@ -20,16 +23,13 @@ pub struct Std { /// /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc crates: Vec<String>, - /// Never use this from outside calls. It is intended for internal use only within `check::Std::make_run` - /// and `check::Std::run`. - custom_stage: Option<u32>, } impl Std { const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"]; - pub fn new(target: TargetSelection) -> Self { - Self { target, crates: vec![], custom_stage: None } + pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self { + Self { build_compiler, target, crates: vec![] } } } @@ -48,14 +48,11 @@ impl Step for Std { fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); - - let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 1 { - run.builder.top_stage - } else { - 1 - }; - - run.builder.ensure(Std { target: run.target, crates, custom_stage: Some(stage) }); + run.builder.ensure(Std { + build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std), + target: run.target, + crates, + }); } fn run(self, builder: &Builder<'_>) { @@ -66,40 +63,20 @@ impl Step for Std { return; } - let stage = self.custom_stage.unwrap_or(builder.top_stage); - + let build_compiler = self.build_compiler; + let stage = build_compiler.stage; let target = self.target; - let compiler = builder.compiler(stage, builder.config.host_target); - - if stage == 0 { - let mut is_explicitly_called = - builder.paths.iter().any(|p| p.starts_with("library") || p.starts_with("std")); - - if !is_explicitly_called { - for c in Std::CRATE_OR_DEPS { - is_explicitly_called = builder.paths.iter().any(|p| p.starts_with(c)); - } - } - - if is_explicitly_called { - eprintln!("WARNING: stage 0 std is precompiled and does nothing during `x check`."); - } - - // Reuse the stage0 libstd - builder.std(compiler, target); - return; - } let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, Mode::Std, SourceType::InTree, target, Kind::Check, ); - std_cargo(builder, target, compiler.stage, &mut cargo); + std_cargo(builder, target, stage, &mut cargo); if matches!(builder.config.cmd, Subcommand::Fix) { // By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot. cargo.arg("--lib"); @@ -115,16 +92,9 @@ impl Step for Std { Some(stage), ); - let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check"); + let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check"); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); - // We skip populating the sysroot in non-zero stage because that'll lead - // to rlib/rmeta conflicts if std gets built during this session. - if compiler.stage == 0 { - let libdir = builder.sysroot_target_libdir(compiler, target); - let hostdir = builder.sysroot_target_libdir(compiler, compiler.host); - add_to_sysroot(builder, &libdir, &hostdir, &stamp); - } drop(_guard); // don't check test dependencies if we haven't built libtest @@ -140,21 +110,14 @@ impl Step for Std { // Currently only the "libtest" tree of crates does this. let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, Mode::Std, SourceType::InTree, target, Kind::Check, ); - // If we're not in stage 0, tests and examples will fail to compile - // from `core` definitions being loaded from two different `libcore` - // .rmeta and .rlib files. - if compiler.stage == 0 { - cargo.arg("--all-targets"); - } - - std_cargo(builder, target, compiler.stage, &mut cargo); + std_cargo(builder, target, build_compiler.stage, &mut cargo); // Explicitly pass -p for all dependencies krates -- this will force cargo // to also check the tests/benches/examples for these crates, rather @@ -163,18 +126,23 @@ impl Step for Std { cargo.arg("-p").arg(krate); } - let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test"); + let stamp = + build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test"); let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage)); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check("std", self.target)) + Some(StepMetadata::check("std", self.target).built_by(self.build_compiler)) } } +/// Checks rustc using `build_compiler` and copies the built +/// .rmeta files into the sysroot of `build_compiler`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rustc { + /// Compiler that will check this rustc. + pub build_compiler: Compiler, pub target: TargetSelection, /// Whether to build only a subset of crates. /// @@ -185,13 +153,13 @@ pub struct Rustc { } impl Rustc { - pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self { + pub fn new(builder: &Builder<'_>, build_compiler: Compiler, target: TargetSelection) -> Self { let crates = builder .in_tree_crates("rustc-main", Some(target)) .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Self { target, crates } + Self { build_compiler, target, crates } } } @@ -206,40 +174,43 @@ impl Step for Rustc { fn make_run(run: RunConfig<'_>) { let crates = run.make_run_crates(Alias::Compiler); - run.builder.ensure(Rustc { target: run.target, crates }); + run.builder.ensure(Rustc { + target: run.target, + build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Rustc), + crates, + }); } - /// Builds the compiler. + /// Check the compiler. /// - /// This will build the compiler for a particular stage of the build using + /// This will check the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. + /// + /// If we check a stage 2 compiler, we will have to first build a stage 1 compiler to check it. fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let target = self.target; - if compiler.stage != 0 { - // If we're not in stage 0, then we won't have a std from the beta - // compiler around. That means we need to make sure there's one in - // the sysroot for the compiler to find. Otherwise, we're going to - // fail when building crates that need to generate code (e.g., build - // scripts and their dependencies). - builder.std(compiler, compiler.host); - builder.std(compiler, target); - } else { - builder.ensure(Std::new(target)); - } + // Build host std for compiling build scripts + builder.std(build_compiler, build_compiler.host); + + // Build target std so that the checked rustc can link to it during the check + // FIXME: maybe we can a way to only do a check of std here? + // But for that we would have to copy the stdlib rmetas to the sysroot of the build + // compiler, which conflicts with std rlibs, if we also build std. + builder.std(build_compiler, target); let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, Mode::Rustc, SourceType::InTree, target, Kind::Check, ); - rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); + rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates); // Explicitly pass -p for all compiler crates -- this will force cargo // to also check the tests/benches/examples for these crates, rather @@ -254,22 +225,75 @@ impl Step for Rustc { None, ); - let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check"); + let stamp = + build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check"); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); - let libdir = builder.sysroot_target_libdir(compiler, target); - let hostdir = builder.sysroot_target_libdir(compiler, compiler.host); + let libdir = builder.sysroot_target_libdir(build_compiler, target); + let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &stamp); } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check("rustc", self.target)) + Some(StepMetadata::check("rustc", self.target).built_by(self.build_compiler)) + } +} + +/// Prepares a compiler that will check something with the given `mode`. +fn prepare_compiler_for_check( + builder: &Builder<'_>, + target: TargetSelection, + mode: Mode, +) -> Compiler { + let host = builder.host_target; + match mode { + Mode::ToolBootstrap => builder.compiler(0, host), + Mode::ToolStd => { + // These tools require the local standard library to be checked + let build_compiler = builder.compiler(builder.top_stage, host); + + // We need to build the host stdlib to check the tool itself. + // We need to build the target stdlib so that the tool can link to it. + builder.std(build_compiler, host); + // We could only check this library in theory, but `check::Std` doesn't copy rmetas + // into `build_compiler`'s sysroot to avoid clashes with `.rlibs`, so we build it + // instead. + builder.std(build_compiler, target); + build_compiler + } + Mode::ToolRustc | Mode::Codegen => { + // FIXME: this is a hack, see description of Mode::Rustc below + let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage }; + // When checking tool stage N, we check it with compiler stage N-1 + let build_compiler = builder.compiler(stage, host); + builder.ensure(Rustc::new(builder, build_compiler, target)); + build_compiler + } + Mode::Rustc => { + // This is a horrible hack, because we actually change the compiler stage numbering + // here. If you do `x check --stage 1 --host FOO`, we build stage 1 host rustc, + // and use that to check stage 1 FOO rustc (which actually makes that stage 2 FOO + // rustc). + // + // FIXME: remove this and either fix cross-compilation check on stage 2 (which has a + // myriad of other problems) or disable cross-checking on stage 1. + let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage }; + builder.compiler(stage, host) + } + Mode::Std => { + // When checking std stage N, we want to do it with the stage N compiler + // Note: we don't need to build the host stdlib here, because when compiling std, the + // stage 0 stdlib is used to compile build scripts and proc macros. + builder.compiler(builder.top_stage, host) + } } } +/// Checks a single codegen backend. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { + pub build_compiler: Compiler, pub target: TargetSelection, pub backend: &'static str, } @@ -284,8 +308,10 @@ impl Step for CodegenBackend { } fn make_run(run: RunConfig<'_>) { + // FIXME: only check the backend(s) that were actually selected in run.paths + let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen); for &backend in &["cranelift", "gcc"] { - run.builder.ensure(CodegenBackend { target: run.target, backend }); + run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend }); } } @@ -296,15 +322,13 @@ impl Step for CodegenBackend { return; } - let compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let target = self.target; let backend = self.backend; - builder.ensure(Rustc::new(target, builder)); - let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, Mode::Codegen, SourceType::InTree, target, @@ -314,23 +338,25 @@ impl Step for CodegenBackend { cargo .arg("--manifest-path") .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml"))); - rustc_cargo_env(builder, &mut cargo, target, compiler.stage); + rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage); - let _guard = builder.msg_check(backend, target, None); + let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None); - let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend) + let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, backend) .with_prefix("check"); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check(self.backend, self.target)) + Some(StepMetadata::check(self.backend, self.target).built_by(self.build_compiler)) } } +/// Checks Rust analyzer that links to .rmetas from a checked rustc. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RustAnalyzer { + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -351,18 +377,17 @@ impl Step for RustAnalyzer { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustAnalyzer { target: run.target }); + let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::ToolRustc); + run.builder.ensure(RustAnalyzer { build_compiler, target: run.target }); } fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let target = self.target; - builder.ensure(Rustc::new(target, builder)); - let mut cargo = prepare_tool_cargo( builder, - compiler, + build_compiler, Mode::ToolRustc, target, builder.kind, @@ -379,7 +404,7 @@ impl Step for RustAnalyzer { // Cargo's output path in a given stage, compiled by a particular // compiler for the specified target. - let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target)) + let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, Mode::ToolRustc, target)) .with_prefix("rust-analyzer-check"); let _guard = builder.msg_check("rust-analyzer artifacts", target, None); @@ -387,7 +412,7 @@ impl Step for RustAnalyzer { } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check("rust-analyzer", self.target)) + Some(StepMetadata::check("rust-analyzer", self.target).built_by(self.build_compiler)) } } @@ -417,19 +442,11 @@ impl Step for Compiletest { } else { Mode::ToolStd }; - - let compiler = builder.compiler( - if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage }, - builder.config.host_target, - ); - - if mode != Mode::ToolBootstrap { - builder.ensure(Rustc::new(self.target, builder)); - } + let build_compiler = prepare_compiler_for_check(builder, self.target, mode); let mut cargo = prepare_tool_cargo( builder, - compiler, + build_compiler, mode, self.target, builder.kind, @@ -442,7 +459,7 @@ impl Step for Compiletest { cargo.arg("--all-targets"); - let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target)) + let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, self.target)) .with_prefix("compiletest-check"); let _guard = builder.msg_check("compiletest artifacts", self.target, None); @@ -460,12 +477,15 @@ macro_rules! tool_check_step { // The part of this path after the final '/' is also used as a display name. path: $path:literal $(, alt_path: $alt_path:literal )* + , mode: $mode:path + $(, allow_features: $allow_features:expr )? $(, default: $default:literal )? $( , )? } ) => { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { + pub build_compiler: Compiler, pub target: TargetSelection, } @@ -480,16 +500,30 @@ macro_rules! tool_check_step { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure($name { target: run.target }); + let target = run.target; + let build_compiler = prepare_compiler_for_check(run.builder, target, $mode); + + // It doesn't make sense to cross-check bootstrap tools + if $mode == Mode::ToolBootstrap && target != run.builder.host_target { + println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path)); + return; + }; + + run.builder.ensure($name { target, build_compiler }); } fn run(self, builder: &Builder<'_>) { - let Self { target } = self; - run_tool_check_step(builder, target, stringify!($name), $path); + let Self { target, build_compiler } = self; + let allow_features = { + let mut _value = ""; + $( _value = $allow_features; )? + _value + }; + run_tool_check_step(builder, build_compiler, target, $path, $mode, allow_features); } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check(stringify!($name), self.target)) + Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler)) } } } @@ -498,19 +532,18 @@ macro_rules! tool_check_step { /// Used by the implementation of `Step::run` in `tool_check_step!`. fn run_tool_check_step( builder: &Builder<'_>, + build_compiler: Compiler, target: TargetSelection, - step_type_name: &str, path: &str, + mode: Mode, + allow_features: &str, ) { let display_name = path.rsplit('/').next().unwrap(); - let compiler = builder.compiler(builder.top_stage, builder.config.host_target); - - builder.ensure(Rustc::new(target, builder)); let mut cargo = prepare_tool_cargo( builder, - compiler, - Mode::ToolRustc, + build_compiler, + mode, target, builder.kind, path, @@ -521,98 +554,65 @@ fn run_tool_check_step( SourceType::InTree, &[], ); + cargo.allow_features(allow_features); + // FIXME: check bootstrap doesn't currently work with --all-targets cargo.arg("--all-targets"); - let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target)) - .with_prefix(&format!("{}-check", step_type_name.to_lowercase())); + let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target)) + .with_prefix(&format!("{display_name}-check")); + + let stage = match mode { + // Mode::ToolRustc is included here because of how msg_sysroot_tool prints stages + Mode::Std | Mode::ToolRustc => build_compiler.stage, + _ => build_compiler.stage + 1, + }; - let _guard = builder.msg_check(format!("{display_name} artifacts"), target, None); + let _guard = + builder.msg_tool(builder.kind, mode, display_name, stage, &build_compiler.host, &target); run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); } -tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" }); +tool_check_step!(Rustdoc { + path: "src/tools/rustdoc", + alt_path: "src/librustdoc", + mode: Mode::ToolRustc +}); // Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead // of a submodule. Since the SourceType only drives the deny-warnings // behavior, treat it as in-tree so that any new warnings in clippy will be // rejected. -tool_check_step!(Clippy { path: "src/tools/clippy" }); -tool_check_step!(Miri { path: "src/tools/miri" }); -tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" }); -tool_check_step!(Rustfmt { path: "src/tools/rustfmt" }); -tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" }); -tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse" }); -tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" }); - -tool_check_step!(Bootstrap { path: "src/bootstrap", default: false }); +tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustc }); +tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustc }); +tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustc }); +tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustc }); +tool_check_step!(MiroptTestTools { + path: "src/tools/miropt-test-tools", + mode: Mode::ToolBootstrap +}); +// We want to test the local std +tool_check_step!(TestFloatParse { + path: "src/tools/test-float-parse", + mode: Mode::ToolStd, + allow_features: tool::TestFloatParse::ALLOW_FEATURES +}); +tool_check_step!(FeaturesStatusDump { + path: "src/tools/features-status-dump", + mode: Mode::ToolBootstrap +}); + +tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false }); // `run-make-support` will be built as part of suitable run-make compiletest test steps, but support // check to make it easier to work on. -tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false }); - -/// Check step for the `coverage-dump` bootstrap tool. The coverage-dump tool -/// is used internally by coverage tests. -/// -/// FIXME(Zalathar): This is temporarily separate from the other tool check -/// steps so that it can use the stage 0 compiler instead of `top_stage`, -/// without introducing conflicts with the stage 0 redesign (#119899). -/// -/// After the stage 0 redesign lands, we can look into using the stage 0 -/// compiler to check all bootstrap tools (#139170). -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) struct CoverageDump; - -impl CoverageDump { - const PATH: &str = "src/tools/coverage-dump"; -} - -impl Step for CoverageDump { - type Output = (); - - /// Most contributors won't care about coverage-dump, so don't make their - /// check builds slower unless they opt in and check it explicitly. - const DEFAULT: bool = false; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path(Self::PATH) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Self {}); - } - - fn run(self, builder: &Builder<'_>) -> Self::Output { - // Make sure we haven't forgotten any fields, if there are any. - let Self {} = self; - let display_name = "coverage-dump"; - let host = builder.config.host_target; - let target = host; - let mode = Mode::ToolBootstrap; - - let compiler = builder.compiler(0, host); - let cargo = prepare_tool_cargo( - builder, - compiler, - mode, - target, - builder.kind, - Self::PATH, - SourceType::InTree, - &[], - ); - - let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target)) - .with_prefix(&format!("{display_name}-check")); - - let _guard = builder.msg_tool( - builder.kind, - mode, - display_name, - compiler.stage, - &compiler.host, - &target, - ); - run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); - } -} +tool_check_step!(RunMakeSupport { + path: "src/tools/run-make-support", + mode: Mode::ToolBootstrap, + default: false +}); + +tool_check_step!(CoverageDump { + path: "src/tools/coverage-dump", + mode: Mode::ToolBootstrap, + default: false +}); diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 1e44b5b67a4..a0371eb7155 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -215,7 +215,7 @@ impl Step for Rustc { builder.std(compiler, compiler.host); builder.std(compiler, target); } else { - builder.ensure(check::Std::new(target)); + builder.ensure(check::Std::new(compiler, target)); } } @@ -287,7 +287,7 @@ macro_rules! lint_any { let target = self.target; if !builder.download_rustc() { - builder.ensure(check::Rustc::new(target, builder)); + builder.ensure(check::Rustc::new(builder, compiler, target)); }; let cargo = prepare_tool_cargo( diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 431c242608b..3e2bdc2d6b5 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1741,17 +1741,19 @@ fn copy_codegen_backends_to_sysroot( } let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend); - let dylib = t!(fs::read_to_string(stamp.path())); - let file = Path::new(&dylib); - let filename = file.file_name().unwrap().to_str().unwrap(); - // change `librustc_codegen_cranelift-xxxxxx.so` to - // `librustc_codegen_cranelift-release.so` - let target_filename = { - let dash = filename.find('-').unwrap(); - let dot = filename.find('.').unwrap(); - format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..]) - }; - builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary); + if stamp.path().exists() { + let dylib = t!(fs::read_to_string(stamp.path())); + let file = Path::new(&dylib); + let filename = file.file_name().unwrap().to_str().unwrap(); + // change `librustc_codegen_cranelift-xxxxxx.so` to + // `librustc_codegen_cranelift-release.so` + let target_filename = { + let dash = filename.find('-').unwrap(); + let dot = filename.find('.').unwrap(); + format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..]) + }; + builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary); + } } } @@ -2162,6 +2164,25 @@ impl Step for Assemble { continue; // Already built as part of rustc } + // FIXME: this is a horrible hack used to make `x check` work when other codegen + // backends are enabled. + // `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot. + // Then it checks codegen backends, which correctly use these rmetas. + // Then it needs to check std, but for that it needs to build stage 1 rustc. + // This copies the build rmetas into the stage0 sysroot, effectively poisoning it, + // because we then have both check and build rmetas in the same sysroot. + // That would be fine on its own. However, when another codegen backend is enabled, + // then building stage 1 rustc implies also building stage 1 codegen backend (even if + // it isn't used for anything). And since that tries to use the poisoned + // rmetas, it fails to build. + // We don't actually need to build rustc-private codegen backends for checking std, + // so instead we skip that. + // Note: this would be also an issue for other rustc-private tools, but that is "solved" + // by check::Std being last in the list of checked things (see + // `Builder::get_step_descriptions`). + if builder.kind == Kind::Check && builder.top_stage == 1 { + continue; + } builder.ensure(CodegenBackend { compiler: build_compiler, target: target_compiler.host, diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index de67a5f77e6..b2056f5cf37 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -263,6 +263,15 @@ impl Step for Llvm { } /// Compile LLVM for `target`. + #[cfg_attr( + feature = "tracing", + instrument( + level = "debug", + name = "Llvm::run", + skip_all, + fields(target = ?self.target), + ), + )] fn run(self, builder: &Builder<'_>) -> LlvmResult { let target = self.target; let target_native = if self.target.starts_with("riscv") { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index ad3f8d89767..b05b34b9b22 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -77,7 +77,7 @@ impl Builder<'_> { *target, ), // doesn't depend on compiler, same as host compiler - _ => self.msg(Kind::Build, build_stage, format_args!("tool {tool}"), *host, *target), + _ => self.msg(kind, build_stage, format_args!("tool {tool}"), *host, *target), } } } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 1c5267cb75e..1d5690a8197 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1240,24 +1240,23 @@ mod snapshot { ctx.config("check") .path("compiler") .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> - [check] cranelift <host> - [check] gcc <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> cranelift 1 <host> + [check] rustc 0 <host> -> gcc 1 <host> "); insta::assert_snapshot!( ctx.config("check") .path("rustc") .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> + [check] rustc 0 <host> -> rustc 1 <host> "); } #[test] + #[should_panic] fn check_compiler_stage_0() { let ctx = TestCtx::new(); ctx.config("check").path("compiler").stage(0).run(); @@ -1272,11 +1271,9 @@ mod snapshot { .stage(1) .render_steps(), @r" [build] llvm <host> - [build] rustc 0 <host> -> rustc 1 <host> - [build] rustc 1 <host> -> std 1 <host> - [check] rustc <host> - [check] cranelift <host> - [check] gcc <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> cranelift 1 <host> + [check] rustc 0 <host> -> gcc 1 <host> "); } @@ -1291,11 +1288,9 @@ mod snapshot { [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 2 <host> -> std 2 <host> - [check] rustc <host> - [check] cranelift <host> - [check] gcc <host> + [check] rustc 1 <host> -> rustc 2 <host> + [check] rustc 1 <host> -> cranelift 2 <host> + [check] rustc 1 <host> -> gcc 2 <host> "); } @@ -1304,30 +1299,24 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("check") - .stage(2) .targets(&[TEST_TRIPLE_1]) .hosts(&[TEST_TRIPLE_1]) .render_steps(), @r" [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 2 <host> -> std 2 <host> [build] rustc 1 <host> -> std 1 <target1> - [build] rustc 2 <host> -> std 2 <target1> - [check] rustc <target1> - [check] Rustdoc <target1> - [check] cranelift <target1> - [check] gcc <target1> - [check] Clippy <target1> - [check] Miri <target1> - [check] CargoMiri <target1> - [check] MiroptTestTools <target1> - [check] Rustfmt <target1> - [check] rust-analyzer <target1> - [check] TestFloatParse <target1> - [check] FeaturesStatusDump <target1> - [check] std <target1> + [check] rustc 1 <host> -> rustc 2 <target1> + [check] rustc 1 <host> -> Rustdoc 2 <target1> + [check] rustc 1 <host> -> cranelift 2 <target1> + [check] rustc 1 <host> -> gcc 2 <target1> + [check] rustc 1 <host> -> Clippy 2 <target1> + [check] rustc 1 <host> -> Miri 2 <target1> + [check] rustc 1 <host> -> CargoMiri 2 <target1> + [check] rustc 1 <host> -> Rustfmt 2 <target1> + [check] rustc 1 <host> -> rust-analyzer 2 <target1> + [check] rustc 1 <host> -> TestFloatParse 2 <target1> + [check] rustc 1 <host> -> std 1 <target1> "); } @@ -1340,11 +1329,12 @@ mod snapshot { .render_steps(), @r" [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> - [check] std <host> + [check] rustc 1 <host> -> std 1 <host> "); } #[test] + #[should_panic] fn check_library_stage_0() { let ctx = TestCtx::new(); ctx.config("check").path("library").stage(0).run(); @@ -1360,7 +1350,7 @@ mod snapshot { .render_steps(), @r" [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> - [check] std <host> + [check] rustc 1 <host> -> std 1 <host> "); } @@ -1376,7 +1366,7 @@ mod snapshot { [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> [build] rustc 1 <host> -> rustc 2 <host> - [check] std <host> + [check] rustc 2 <host> -> std 2 <host> "); } @@ -1390,8 +1380,8 @@ mod snapshot { .render_steps(), @r" [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> - [check] std <target1> - [check] std <target2> + [check] rustc 1 <host> -> std 1 <target1> + [check] rustc 1 <host> -> std 1 <target2> "); } @@ -1402,14 +1392,14 @@ mod snapshot { ctx.config("check") .path("miri") .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> - [check] Miri <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> Miri 1 <host> "); } #[test] + #[should_panic] fn check_miri_stage_0() { let ctx = TestCtx::new(); ctx.config("check").path("miri").stage(0).run(); @@ -1424,10 +1414,8 @@ mod snapshot { .stage(1) .render_steps(), @r" [build] llvm <host> - [build] rustc 0 <host> -> rustc 1 <host> - [build] rustc 1 <host> -> std 1 <host> - [check] rustc <host> - [check] Miri <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> Miri 1 <host> "); } @@ -1442,10 +1430,8 @@ mod snapshot { [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> - [build] rustc 1 <host> -> rustc 2 <host> - [build] rustc 2 <host> -> std 2 <host> - [check] rustc <host> - [check] Miri <host> + [check] rustc 1 <host> -> rustc 2 <host> + [check] rustc 1 <host> -> Miri 2 <host> "); } @@ -1466,9 +1452,9 @@ mod snapshot { .path("compiletest") .args(&["--set", "build.compiletest-use-stage0-libtest=false"]) .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> [check] compiletest <host> "); } @@ -1480,11 +1466,10 @@ mod snapshot { ctx.config("check") .path("rustc_codegen_cranelift") .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> - [check] cranelift <host> - [check] gcc <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> cranelift 1 <host> + [check] rustc 0 <host> -> gcc 1 <host> "); } @@ -1495,10 +1480,9 @@ mod snapshot { ctx.config("check") .path("rust-analyzer") .render_steps(), @r" - [check] std <host> [build] llvm <host> - [check] rustc <host> - [check] rust-analyzer <host> + [check] rustc 0 <host> -> rustc 1 <host> + [check] rustc 0 <host> -> rust-analyzer 1 <host> "); } @@ -1508,12 +1492,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("run-make-support") - .render_steps(), @r" - [check] std <host> - [build] llvm <host> - [check] rustc <host> - [check] RunMakeSupport <host> - "); + .render_steps(), @"[check] rustc 0 <host> -> RunMakeSupport 1 <host>"); } #[test] diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 49b3fec4c35..59693dc3e4c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1025,7 +1025,7 @@ impl Config { || bench_stage.is_some(); config.stage = match config.cmd { - Subcommand::Check { .. } => flags_stage.or(check_stage).unwrap_or(0), + Subcommand::Check { .. } => flags_stage.or(check_stage).unwrap_or(1), Subcommand::Clippy { .. } | Subcommand::Fix => flags_stage.or(check_stage).unwrap_or(1), // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden. Subcommand::Doc { .. } => { @@ -1052,9 +1052,16 @@ impl Config { }; // Now check that the selected stage makes sense, and if not, print a warning and end - if let (0, Subcommand::Build) = (config.stage, &config.cmd) { - eprintln!("WARNING: cannot build anything on stage 0. Use at least stage 1."); - exit!(1); + match (config.stage, &config.cmd) { + (0, Subcommand::Build) => { + eprintln!("WARNING: cannot build anything on stage 0. Use at least stage 1."); + exit!(1); + } + (0, Subcommand::Check { .. }) => { + eprintln!("WARNING: cannot check anything on stage 0. Use at least stage 1."); + exit!(1); + } + _ => {} } // CI should always run stage 2 builds, unless it specifically states otherwise diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index f5a958618f9..424f211c7d4 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -451,4 +451,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The `spellcheck:fix` tidy extra check argument has been removed, use `--bless` instead", }, + ChangeInfo { + change_id: 143048, + severity: ChangeSeverity::Warning, + summary: "The default check stage has been changed to 1. It is no longer possible to `x check` with stage 0. All check commands have to be on stage 1+. Bootstrap tools can now also only be checked for the host target.", + }, + ChangeInfo { + change_id: 143577, + severity: ChangeSeverity::Warning, + summary: "`download-rustc` has been temporarily disabled for the library profile due to implementation bugs (see #142505).", + }, ]; diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/Dockerfile index d2f1b9400ad..e3ba51e8ffc 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/Dockerfile @@ -15,19 +15,15 @@ COPY scripts/crosstool-ng-build.sh /scripts/ COPY host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh -WORKDIR /build - -RUN apt-get install -y --no-install-recommends rpm2cpio cpio -COPY scripts/shared.sh scripts/build-powerpc64le-toolchain.sh /build/ -RUN ./build-powerpc64le-toolchain.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +ENV PATH=$PATH:/x-tools/powerpc64le-unknown-linux-gnu/bin + ENV \ - AR_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-ar \ - CC_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-gcc \ - CXX_powerpc64le_unknown_linux_gnu=powerpc64le-linux-gnu-g++ + AR_powerpc64le_unknown_linux_gnu=powerpc64le-unknown-linux-gnu-ar \ + CC_powerpc64le_unknown_linux_gnu=powerpc64le-unknown-linux-gnu-gcc \ + CXX_powerpc64le_unknown_linux_gnu=powerpc64le-unknown-linux-gnu-g++ ENV HOSTS=powerpc64le-unknown-linux-gnu diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig index 363e5850894..5fbf138cdd7 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig @@ -9,6 +9,7 @@ CT_ARCH_64=y # CT_DEMULTILIB is not set CT_ARCH_ARCH="powerpc64le" CT_KERNEL_LINUX=y -CT_LINUX_V_4_19=y +CT_LINUX_V_3_10=y +CT_GLIBC_V_2_17=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/Dockerfile index f045b2a5f65..601c8e90585 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/Dockerfile @@ -15,12 +15,6 @@ COPY scripts/crosstool-ng-build.sh /scripts/ COPY host-x86_64/dist-powerpc64le-linux-musl/powerpc64le-unknown-linux-musl.defconfig /tmp/crosstool.defconfig RUN /scripts/crosstool-ng-build.sh -WORKDIR /build - -RUN apt-get install -y --no-install-recommends rpm2cpio cpio -COPY scripts/shared.sh scripts/build-powerpc64le-toolchain.sh /build/ -RUN ./build-powerpc64le-toolchain.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile index 7a8056b70dc..8bbcc18e2be 100644 --- a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile @@ -45,11 +45,11 @@ COPY host-x86_64/pr-check-1/validate-toolstate.sh /scripts/ # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT \ /scripts/check-default-config-profiles.sh && \ - python3 ../x.py build --stage 1 src/tools/build-manifest && \ + python3 ../x.py build src/tools/build-manifest && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ - python3 ../x.py check --stage 1 --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ - python3 ../x.py check --stage 1 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ + python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ + python3 ../x.py check --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/validate-toolstate.sh && \ reuse --include-submodules lint && \ python3 ../x.py test collect-license-metadata && \ diff --git a/src/ci/docker/scripts/build-powerpc64le-toolchain.sh b/src/ci/docker/scripts/build-powerpc64le-toolchain.sh deleted file mode 100755 index 56ea28b6ca5..00000000000 --- a/src/ci/docker/scripts/build-powerpc64le-toolchain.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -source shared.sh - -BINUTILS=2.32 -GCC=8.3.0 -TARGET=powerpc64le-linux-gnu -SYSROOT=/usr/local/$TARGET/sysroot - -# First, download the CentOS7 glibc.ppc64le and relevant header files. -# (upstream ppc64le support wasn't added until 2.19, which el7 backported.) -mkdir -p $SYSROOT -pushd $SYSROOT - -# centos_base=http://vault.centos.org/altarch/7.3.1611/os/ppc64le/Packages/ -# Mirrored from centos_base above -centos_base=https://ci-mirrors.rust-lang.org/rustc -glibc_v=2.17-157-2020-11-25.el7 -kernel_v=3.10.0-514-2020-11-25.el7 -for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do - curl $centos_base/$package.ppc64le.rpm | \ - rpm2cpio - | cpio -idm -done - -ln -sT lib64 lib -ln -sT lib64 usr/lib - -popd - -# Next, download and build binutils. -mkdir binutils-$TARGET -pushd binutils-$TARGET -curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.xz | tar xJf - -mkdir binutils-build -cd binutils-build -hide_output ../binutils-$BINUTILS/configure --target=$TARGET --with-sysroot=$SYSROOT -hide_output make -j10 -hide_output make install -popd -rm -rf binutils-$TARGET - -# Finally, download and build gcc. -mkdir gcc-$TARGET -pushd gcc-$TARGET -curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.xz | tar xJf - -cd gcc-$GCC -hide_output ./contrib/download_prerequisites - -mkdir ../gcc-build -cd ../gcc-build -hide_output ../gcc-$GCC/configure \ - --enable-languages=c,c++ \ - --target=$TARGET \ - --with-cpu=power8 \ - --with-sysroot=$SYSROOT \ - --disable-libcilkrts \ - --disable-multilib \ - --disable-nls \ - --disable-libgomp \ - --disable-libquadmath \ - --disable-libssp \ - --disable-libvtv \ - --disable-libcilkrt \ - --disable-libada \ - --disable-libsanitizer \ - --disable-libquadmath-support \ - --disable-lto -hide_output hide_output make -j10 -hide_output make install - -popd -rm -rf gcc-$TARGET diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index 9040ef637be..e80ff85edad 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -1,7 +1,5 @@ # \*-unknown-netbsd -**Tier: 3** - [NetBSD] multi-platform 4.4BSD-based UNIX-like operating system. [NetBSD]: https://www.NetBSD.org/ @@ -11,19 +9,19 @@ where `$ARCH` specifies the target processor architecture and `-$SUFFIX` (optional) might indicate the ABI. The following targets are currently defined running NetBSD: -| Target name | NetBSD Platform | -|--------------------------------|-----------------| -| `x86_64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | -| `armv7-unknown-netbsd-eabihf` | [32-bit ARMv7 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | -| `armv6-unknown-netbsd-eabihf` | [32-bit ARMv6 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | -| `aarch64-unknown-netbsd` | [64-bit ARM systems, little-endian](https://wiki.netbsd.org/ports/evbarm/) | -| `aarch64_be-unknown-netbsd` | [64-bit ARM systems, big-endian](https://wiki.netbsd.org/ports/evbarm/) | -| `i586-unknown-netbsd` | [32-bit i386, restricted to Pentium](https://wiki.netbsd.org/ports/i386/) | -| `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | -| `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | -| `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | -| `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) | -| `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | +| Target tier | Target name | NetBSD Platform | +|---------------------|-------------------------------|--------------------------------------------------------------------------------------| +| 2 (with host tools) | `x86_64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | +| 3 | `armv7-unknown-netbsd-eabihf` | [32-bit ARMv7 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| 3 | `armv6-unknown-netbsd-eabihf` | [32-bit ARMv6 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| 3 | `aarch64-unknown-netbsd` | [64-bit ARM systems, little-endian](https://wiki.netbsd.org/ports/evbarm/) | +| 3 | `aarch64_be-unknown-netbsd` | [64-bit ARM systems, big-endian](https://wiki.netbsd.org/ports/evbarm/) | +| 3 | `i586-unknown-netbsd` | [32-bit i386, restricted to Pentium](https://wiki.netbsd.org/ports/i386/) | +| 3 | `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | +| 3 | `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | +| 3 | `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | +| 3 | `riscv64gc-unknown-netbsd` | [64-bit RISC-V](https://wiki.netbsd.org/ports/riscv/) | +| 3 | `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | All use the "native" `stdc++` library which goes along with the natively supplied GNU C++ compiler for the given OS version. Many of the bootstraps diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index d4a25efec17..90ce7f8b225 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -1,3 +1,3 @@ % Rust Documentation -This has been moved [into the book](book/documentation.html). +This has been moved [into the rustdoc book](rustdoc/index.html). diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5cd5c434521..c2f3da18cd3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1834,7 +1834,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T }; DynTrait(bounds, lifetime) } - TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), + TyKind::FnPtr(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), TyKind::UnsafeBinder(unsafe_binder_ty) => { UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx))) } @@ -2558,7 +2558,7 @@ fn clean_path_segment<'tcx>( } fn clean_bare_fn_ty<'tcx>( - bare_fn: &hir::BareFnTy<'tcx>, + bare_fn: &hir::FnPtrTy<'tcx>, cx: &mut DocContext<'tcx>, ) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, |cx| { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 41c3f03b91b..0078671fcc5 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -25,7 +25,6 @@ use std::str::FromStr; use std::{fmt, fs}; use indexmap::IndexMap; -use itertools::Itertools; use regex::Regex; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; @@ -44,6 +43,7 @@ use crate::docfs::PathError; use crate::error::Error; use crate::formats::Impl; use crate::formats::item_type::ItemType; +use crate::html::format::join_with_double_colon; use crate::html::layout; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::search_index::{SerializedSearchIndex, build_index}; @@ -608,7 +608,7 @@ impl TypeAliasPart { for &(type_alias_fqp, type_alias_item) in type_aliases { cx.id_map.borrow_mut().clear(); cx.deref_id_map.borrow_mut().clear(); - let type_alias_fqp = (*type_alias_fqp).iter().join("::"); + let type_alias_fqp = join_with_double_colon(&type_alias_fqp); if let Some(ret) = &mut ret { ret.aliases.push(type_alias_fqp); } else { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f51b35097f6..abf3f3fcedd 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -2,8 +2,6 @@ //! the `clean` types but with some fields removed or stringified to simplify the output and not //! expose unstable compiler internals. -#![allow(rustc::default_hash_types)] - use rustc_abi::ExternAbi; use rustc_ast::ast; use rustc_attr_data_structures::{self as attrs, DeprecatedSince}; diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs index 105477093b5..55e27a05f3c 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs @@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, ty::FnDef(..) | ty::FnPtr(..) => { let mut applicability = Applicability::MaybeIncorrect; - if to_nbits >= cx.tcx.data_layout.pointer_size.bits() && !cast_to.is_usize() { + if to_nbits >= cx.tcx.data_layout.pointer_size().bits() && !cast_to.is_usize() { let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs index 700b7d0d426..4da79205e20 100644 --- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs @@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); - if to_nbits < cx.tcx.data_layout.pointer_size.bits() { + if to_nbits < cx.tcx.data_layout.pointer_size().bits() { span_lint_and_sugg( cx, FN_TO_NUMERIC_CAST_WITH_TRUNCATION, diff --git a/src/tools/clippy/clippy_lints/src/casts/utils.rs b/src/tools/clippy/clippy_lints/src/casts/utils.rs index 318a1646477..d846d78b9ee 100644 --- a/src/tools/clippy/clippy_lints/src/casts/utils.rs +++ b/src/tools/clippy/clippy_lints/src/casts/utils.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr}; /// integral type. pub(super) fn int_ty_to_nbits(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<u64> { match ty.kind() { - ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(tcx.data_layout.pointer_size.bits()), + ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(tcx.data_layout.pointer_size().bits()), ty::Int(i) => i.bit_width(), ty::Uint(i) => i.bit_width(), _ => None, diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 7463d7b5c3b..5099df3fa02 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -824,7 +824,7 @@ impl TyCoercionStability { TyKind::Slice(_) | TyKind::Array(..) | TyKind::Ptr(_) - | TyKind::BareFn(_) + | TyKind::FnPtr(_) | TyKind::Pat(..) | TyKind::Never | TyKind::Tup(_) diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 098571a5351..c828fc57f76 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -35,7 +35,7 @@ declare_lint_pass!(UnportableVariant => [ENUM_CLIKE_UNPORTABLE_VARIANT]); impl<'tcx> LateLintPass<'tcx> for UnportableVariant { #[expect(clippy::cast_possible_wrap)] fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if cx.tcx.data_layout.pointer_size.bits() != 64 { + if cx.tcx.data_layout.pointer_size().bits() != 64 { return; } if let ItemKind::Enum(_, _, def) = &item.kind { diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 8fe0c9d60f9..caf17c10484 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -13,7 +13,7 @@ use rustc_hir::intravisit::{ walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, walk_where_predicate, }; use rustc_hir::{ - AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, + AmbigArg, BodyId, FnDecl, FnPtrTy, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, Node, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, WherePredicateKind, lang_items, @@ -480,7 +480,7 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_, AmbigArg>) { match ty.kind { - TyKind::BareFn(&BareFnTy { decl, .. }) => { + TyKind::FnPtr(&FnPtrTy { decl, .. }) => { let mut sub_visitor = RefVisitor::new(self.cx); sub_visitor.visit_fn_decl(decl); self.nested_elision_site_lts.append(&mut sub_visitor.all_lts()); diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index 0704653385f..52c6fda8097 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -50,7 +50,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), // function types bring a lot of overhead - TyKind::BareFn(bare) if bare.abi == ExternAbi::Rust => (50 * self.nest, 1), + TyKind::FnPtr(fn_ptr) if fn_ptr.abi == ExternAbi::Rust => (50 * self.nest, 1), TyKind::TraitObject(param_bounds, _) => { let has_lifetime_parameters = param_bounds.iter().any(|bound| { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index e6396987cc6..42254ec8e92 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -838,7 +838,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { (PinnedRef(ll, l), PinnedRef(rl, r)) => { both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, - (BareFn(l), BareFn(r)) => { + (FnPtr(l), FnPtr(r)) => { l.safety == r.safety && eq_ext(&l.ext, &r.ext) && over(&l.generic_params, &r.generic_params, eq_generic_param) diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 407e92d88fb..ce61fffe0de 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -372,17 +372,17 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), - TyKind::BareFn(bare_fn) => ( - if bare_fn.safety.is_unsafe() { + TyKind::FnPtr(fn_ptr) => ( + if fn_ptr.safety.is_unsafe() { Pat::Str("unsafe") - } else if bare_fn.abi != ExternAbi::Rust { + } else if fn_ptr.abi != ExternAbi::Rust { Pat::Str("extern") } else { Pat::MultiStr(&["fn", "extern"]) }, - match bare_fn.decl.output { + match fn_ptr.decl.output { FnRetTy::DefaultReturn(_) => { - if let [.., ty] = bare_fn.decl.inputs { + if let [.., ty] = fn_ptr.decl.inputs { ty_search_pat(ty).1 } else { Pat::Str("(") diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 09299c869dc..ba0376e4d40 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -918,7 +918,7 @@ fn mir_is_empty<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<boo // Get the length from the slice, using the same formula as // [`ConstValue::try_get_slice_bytes_for_diagnostics`]. let a = tcx.global_alloc(alloc_id).unwrap_memory().inner(); - let ptr_size = tcx.data_layout.pointer_size; + let ptr_size = tcx.data_layout.pointer_size(); if a.size() < offset + 2 * ptr_size { // (partially) dangling reference return None; diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c37231d0931..0ca494f16e3 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1283,20 +1283,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - TyKind::BareFn(bfn) => { - bfn.safety.hash(&mut self.s); - bfn.abi.hash(&mut self.s); - for arg in bfn.decl.inputs { + TyKind::FnPtr(fn_ptr) => { + fn_ptr.safety.hash(&mut self.s); + fn_ptr.abi.hash(&mut self.s); + for arg in fn_ptr.decl.inputs { self.hash_ty(arg); } - std::mem::discriminant(&bfn.decl.output).hash(&mut self.s); - match bfn.decl.output { + std::mem::discriminant(&fn_ptr.decl.output).hash(&mut self.s); + match fn_ptr.decl.output { FnRetTy::DefaultReturn(_) => {}, FnRetTy::Return(ty) => { self.hash_ty(ty); }, } - bfn.decl.c_variadic.hash(&mut self.s); + fn_ptr.decl.c_variadic.hash(&mut self.s); }, TyKind::Tup(ty_list) => { for ty in *ty_list { diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 56c19794854..a4e93f9222c 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -894,7 +894,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { start_abi, &[func_arg], Some(&ret_place), - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; // Restore the old active thread frame. diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 63578912c24..425a136dfa5 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -436,7 +436,7 @@ pub fn create_ecx<'tcx>( ImmTy::from_uint(sigpipe, ecx.machine.layouts.u8), ], Some(&ret_place), - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; } MiriEntryFnType::MiriStart => { @@ -445,7 +445,7 @@ pub fn create_ecx<'tcx>( ExternAbi::Rust, &[argc, argv], Some(&ret_place), - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; } } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b259243602e..c150dc16b07 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -444,7 +444,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { caller_abi: ExternAbi, args: &[ImmTy<'tcx>], dest: Option<&MPlaceTy<'tcx>>, - stack_pop: StackPopCleanup, + cont: ReturnContinuation, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -472,7 +472,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &args.iter().map(|a| FnArg::Copy(a.clone().into())).collect::<Vec<_>>(), /*with_caller_location*/ false, &dest.into(), - stack_pop, + cont, ) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 4f3dc485325..693b8916d89 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1199,7 +1199,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ExternAbi::Rust, &[], None, - StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable }, + ReturnContinuation::Goto { ret: None, unwind: mir::UnwindAction::Unreachable }, )?; interp_ok(()) } diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index a6bce830149..9490761d0c9 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -92,7 +92,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &[data.clone()], None, // Directly return to caller. - StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue }, + ReturnContinuation::Goto { ret, unwind: mir::UnwindAction::Continue }, )?; // We ourselves will return `0`, eventually (will be overwritten if we catch a panic). @@ -143,7 +143,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &[catch_unwind.data, payload], None, // Directly return to caller of `catch_unwind`. - StackPopCleanup::Goto { + ReturnContinuation::Goto { ret: catch_unwind.ret, // `catch_fn` must not unwind. unwind: mir::UnwindAction::Unreachable, @@ -172,7 +172,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::Rust, &[this.mplace_to_ref(&msg)?], None, - StackPopCleanup::Goto { ret: None, unwind }, + ReturnContinuation::Goto { ret: None, unwind }, ) } @@ -191,7 +191,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::Rust, &[this.mplace_to_ref(&msg)?], None, - StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable }, + ReturnContinuation::Goto { ret: None, unwind: mir::UnwindAction::Unreachable }, ) } @@ -220,7 +220,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::Rust, &[index, len], None, - StackPopCleanup::Goto { ret: None, unwind }, + ReturnContinuation::Goto { ret: None, unwind }, )?; } MisalignedPointerDereference { required, found } => { @@ -241,7 +241,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::Rust, &[required, found], None, - StackPopCleanup::Goto { ret: None, unwind }, + ReturnContinuation::Goto { ret: None, unwind }, )?; } @@ -254,7 +254,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::Rust, &[], None, - StackPopCleanup::Goto { ret: None, unwind }, + ReturnContinuation::Goto { ret: None, unwind }, )?; } } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 2fc42c13edd..eb21abc2a45 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -359,6 +359,63 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(0)) } + fn clock_nanosleep( + &mut self, + clock_id: &OpTy<'tcx>, + flags: &OpTy<'tcx>, + timespec: &OpTy<'tcx>, + rem: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + let clockid_t_size = this.libc_ty_layout("clockid_t").size; + + let clock_id = this.read_scalar(clock_id)?.to_int(clockid_t_size)?; + let timespec = this.deref_pointer_as(timespec, this.libc_ty_layout("timespec"))?; + let flags = this.read_scalar(flags)?.to_i32()?; + let _rem = this.read_pointer(rem)?; // Signal handlers are not supported, so rem will never be written to. + + // The standard lib through sleep_until only needs CLOCK_MONOTONIC + if clock_id != this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)? { + throw_unsup_format!("clock_nanosleep: only CLOCK_MONOTONIC is supported"); + } + + let duration = match this.read_timespec(×pec)? { + Some(duration) => duration, + None => { + return this.set_last_error_and_return_i32(LibcError("EINVAL")); + } + }; + + let timeout_anchor = if flags == 0 { + // No flags set, the timespec should be interperted as a duration + // to sleep for + TimeoutAnchor::Relative + } else if flags == this.eval_libc_i32("TIMER_ABSTIME") { + // Only flag TIMER_ABSTIME set, the timespec should be interperted as + // an absolute time. + TimeoutAnchor::Absolute + } else { + // The standard lib (through `sleep_until`) only needs TIMER_ABSTIME + throw_unsup_format!( + "`clock_nanosleep` unsupported flags {flags}, only no flags or \ + TIMER_ABSTIME is supported" + ); + }; + + this.block_thread( + BlockReason::Sleep, + Some((TimeoutClock::Monotonic, timeout_anchor, duration)), + callback!( + @capture<'tcx> {} + |_this, unblock: UnblockKind| { + assert_eq!(unblock, UnblockKind::TimedOut); + interp_ok(()) + } + ), + ); + interp_ok(Scalar::from_i32(0)) + } + #[allow(non_snake_case)] fn Sleep(&mut self, timeout: &OpTy<'tcx>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs index 46a417689a2..7182637437a 100644 --- a/src/tools/miri/src/shims/tls.rs +++ b/src/tools/miri/src/shims/tls.rs @@ -325,7 +325,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::System { unwind: false }, &[null_ptr.clone(), ImmTy::from_scalar(reason, this.machine.layouts.u32), null_ptr], None, - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; interp_ok(()) } @@ -346,7 +346,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::C { unwind: false }, &[ImmTy::from_scalar(data, this.machine.layouts.mut_raw_ptr)], None, - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; return interp_ok(Poll::Pending); @@ -383,7 +383,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ExternAbi::C { unwind: false }, &[ImmTy::from_scalar(ptr, this.machine.layouts.mut_raw_ptr)], None, - StackPopCleanup::Root { cleanup: true }, + ReturnContinuation::Stop { cleanup: true }, )?; return interp_ok(Poll::Pending); diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 438a9b420be..548eabb1b9f 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -967,6 +967,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = this.nanosleep(duration, rem)?; this.write_scalar(result, dest)?; } + "clock_nanosleep" => { + // Currently this function does not exist on all Unixes, e.g. on macOS. + this.check_target_os( + &["freebsd", "linux", "android", "solaris", "illumos"], + link_name, + )?; + let [clock_id, flags, req, rem] = + this.check_shim(abi, CanonAbi::C, link_name, args)?; + let result = this.clock_nanosleep(clock_id, flags, req, rem)?; + this.write_scalar(result, dest)?; + } "sched_getaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "android"], link_name)?; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-time.rs b/src/tools/miri/tests/pass-dep/libc/libc-time.rs index e53201e0bc5..e8957846ad5 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-time.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-time.rs @@ -1,5 +1,6 @@ //@ignore-target: windows # no libc time APIs on Windows //@compile-flags: -Zmiri-disable-isolation +use std::time::{Duration, Instant}; use std::{env, mem, ptr}; fn main() { @@ -20,6 +21,19 @@ fn main() { test_localtime_r_future_32b(); #[cfg(target_pointer_width = "64")] test_localtime_r_future_64b(); + + test_nanosleep(); + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "android", + target_os = "solaris", + target_os = "illumos" + ))] + { + test_clock_nanosleep::absolute(); + test_clock_nanosleep::relative(); + } } /// Tests whether clock support exists at all @@ -315,3 +329,103 @@ fn test_localtime_r_multiple_calls_deduplication() { NUM_CALLS - 1 ); } + +fn test_nanosleep() { + let start_test_sleep = Instant::now(); + let duration_zero = libc::timespec { tv_sec: 0, tv_nsec: 0 }; + let remainder = ptr::null_mut::<libc::timespec>(); + let is_error = unsafe { libc::nanosleep(&duration_zero, remainder) }; + assert_eq!(is_error, 0); + assert!(start_test_sleep.elapsed() < Duration::from_millis(10)); + + let start_test_sleep = Instant::now(); + let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 }; + let remainder = ptr::null_mut::<libc::timespec>(); + let is_error = unsafe { libc::nanosleep(&duration_100_millis, remainder) }; + assert_eq!(is_error, 0); + assert!(start_test_sleep.elapsed() > Duration::from_millis(100)); +} + +#[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "android", + target_os = "solaris", + target_os = "illumos" +))] +mod test_clock_nanosleep { + use super::*; + + /// Helper function used to create an instant in the future + fn add_100_millis(mut ts: libc::timespec) -> libc::timespec { + // While tv_nsec has type `c_long` tv_sec has type `time_t`. These might + // end up as different types (for example: like i32 and i64). + const SECOND: libc::c_long = 1_000_000_000; + ts.tv_nsec += SECOND / 10; + // If this pushes tv_nsec to SECOND or higher, we need to overflow to tv_sec. + ts.tv_sec += (ts.tv_nsec / SECOND) as libc::time_t; + ts.tv_nsec %= SECOND; + ts + } + + /// Helper function to get the current time for testing relative sleeps + fn timespec_now(clock: libc::clockid_t) -> libc::timespec { + let mut timespec = mem::MaybeUninit::<libc::timespec>::uninit(); + let is_error = unsafe { libc::clock_gettime(clock, timespec.as_mut_ptr()) }; + assert_eq!(is_error, 0); + unsafe { timespec.assume_init() } + } + + pub fn absolute() { + let start_test_sleep = Instant::now(); + let before_start = libc::timespec { tv_sec: 0, tv_nsec: 0 }; + let remainder = ptr::null_mut::<libc::timespec>(); + let error = unsafe { + // this will not sleep since unix time zero is in the past + libc::clock_nanosleep( + libc::CLOCK_MONOTONIC, + libc::TIMER_ABSTIME, + &before_start, + remainder, + ) + }; + assert_eq!(error, 0); + assert!(start_test_sleep.elapsed() < Duration::from_millis(10)); + + let start_test_sleep = Instant::now(); + let hunderd_millis_after_start = add_100_millis(timespec_now(libc::CLOCK_MONOTONIC)); + let remainder = ptr::null_mut::<libc::timespec>(); + let error = unsafe { + libc::clock_nanosleep( + libc::CLOCK_MONOTONIC, + libc::TIMER_ABSTIME, + &hunderd_millis_after_start, + remainder, + ) + }; + assert_eq!(error, 0); + assert!(start_test_sleep.elapsed() > Duration::from_millis(100)); + } + + pub fn relative() { + const NO_FLAGS: i32 = 0; + + let start_test_sleep = Instant::now(); + let duration_zero = libc::timespec { tv_sec: 0, tv_nsec: 0 }; + let remainder = ptr::null_mut::<libc::timespec>(); + let error = unsafe { + libc::clock_nanosleep(libc::CLOCK_MONOTONIC, NO_FLAGS, &duration_zero, remainder) + }; + assert_eq!(error, 0); + assert!(start_test_sleep.elapsed() < Duration::from_millis(10)); + + let start_test_sleep = Instant::now(); + let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 }; + let remainder = ptr::null_mut::<libc::timespec>(); + let error = unsafe { + libc::clock_nanosleep(libc::CLOCK_MONOTONIC, NO_FLAGS, &duration_100_millis, remainder) + }; + assert_eq!(error, 0); + assert!(start_test_sleep.elapsed() > Duration::from_millis(100)); + } +} diff --git a/src/tools/miri/tests/pass/shims/time.rs b/src/tools/miri/tests/pass/shims/time.rs index 226f04ade0f..ef0b400f1a7 100644 --- a/src/tools/miri/tests/pass/shims/time.rs +++ b/src/tools/miri/tests/pass/shims/time.rs @@ -1,4 +1,5 @@ //@compile-flags: -Zmiri-disable-isolation +#![feature(thread_sleep_until)] use std::time::{Duration, Instant, SystemTime}; @@ -15,6 +16,14 @@ fn test_sleep() { assert!((after - before).as_millis() >= 100); } +fn test_sleep_until() { + let before = Instant::now(); + let hunderd_millis_after_start = before + Duration::from_millis(100); + std::thread::sleep_until(hunderd_millis_after_start); + let after = Instant::now(); + assert!((after - before).as_millis() >= 100); +} + fn main() { // Check `SystemTime`. let now1 = SystemTime::now(); @@ -49,4 +58,5 @@ fn main() { duration_sanity(diff); test_sleep(); + test_sleep_until(); } diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index caa8f28d8e2..7432a82080d 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -570,12 +570,6 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1021,6 +1015,15 @@ dependencies = [ ] [[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +dependencies = [ + "memoffset", +] + +[[package]] name = "itertools" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1428,6 +1431,16 @@ dependencies = [ ] [[package]] +name = "papaya" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f" +dependencies = [ + "equivalent", + "seize", +] + +[[package]] name = "parking_lot" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1955,16 +1968,18 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781" +checksum = "2e235afdb8e510f38a07138fbe5a0b64691894358a9c0cbd813b1aade110efc9" dependencies = [ "boxcar", "crossbeam-queue", - "dashmap", + "crossbeam-utils", "hashbrown 0.15.4", "hashlink", "indexmap", + "intrusive-collections", + "papaya", "parking_lot", "portable-atomic", "rayon", @@ -1978,17 +1993,16 @@ dependencies = [ [[package]] name = "salsa-macro-rules" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c" +checksum = "2edb86a7e9c91f6d30c9ce054312721dbe773a162db27bbfae834d16177b30ce" [[package]] name = "salsa-macros" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378" +checksum = "d0778d6e209051bc4e75acfe83bcd7848601ec3dbe9c3dbb982829020e9128af" dependencies = [ - "heck", "proc-macro2", "quote", "syn", @@ -2026,6 +2040,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "seize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 0a8e6feb46e..d268ce5b0bb 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -49,6 +49,8 @@ debug = 2 # ungrammar = { path = "../ungrammar" } # salsa = { path = "../salsa" } +# salsa-macros = { path = "../salsa/components/salsa-macros" } +# salsa-macro-rules = { path = "../salsa/components/salsa-macro-rules" } [workspace.dependencies] # local crates @@ -136,8 +138,8 @@ rayon = "1.10.0" rowan = "=0.15.15" # Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work # on impls without it -salsa = { version = "0.22.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] } -salsa-macros = "0.22.0" +salsa = { version = "0.23.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] } +salsa-macros = "0.23.0" semver = "1.0.26" serde = { version = "1.0.219" } serde_derive = { version = "1.0.219" } diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 2a87b152487..8c9393bcc93 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -6,6 +6,7 @@ //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how //! actual IO is done and lowered to input. +use std::error::Error; use std::hash::BuildHasherDefault; use std::{fmt, mem, ops}; @@ -22,7 +23,49 @@ use vfs::{AbsPathBuf, AnchoredPath, FileId, VfsPath, file_set::FileSet}; use crate::{CrateWorkspaceData, EditionedFileId, FxIndexSet, RootQueryDb}; -pub type ProcMacroPaths = FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), String>>; +pub type ProcMacroPaths = + FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), ProcMacroLoadingError>>; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ProcMacroLoadingError { + Disabled, + FailedToBuild, + MissingDylibPath, + NotYetBuilt, + NoProcMacros, + ProcMacroSrvError(Box<str>), +} +impl ProcMacroLoadingError { + pub fn is_hard_error(&self) -> bool { + match self { + ProcMacroLoadingError::Disabled | ProcMacroLoadingError::NotYetBuilt => false, + ProcMacroLoadingError::FailedToBuild + | ProcMacroLoadingError::MissingDylibPath + | ProcMacroLoadingError::NoProcMacros + | ProcMacroLoadingError::ProcMacroSrvError(_) => true, + } + } +} + +impl Error for ProcMacroLoadingError {} +impl fmt::Display for ProcMacroLoadingError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ProcMacroLoadingError::Disabled => write!(f, "proc-macro expansion is disabled"), + ProcMacroLoadingError::FailedToBuild => write!(f, "proc-macro failed to build"), + ProcMacroLoadingError::MissingDylibPath => { + write!(f, "proc-macro crate build data is missing a dylib path") + } + ProcMacroLoadingError::NotYetBuilt => write!(f, "proc-macro not yet built"), + ProcMacroLoadingError::NoProcMacros => { + write!(f, "proc macro library has no proc macros") + } + ProcMacroLoadingError::ProcMacroSrvError(msg) => { + write!(f, "proc macro server error: {msg}") + } + } + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct SourceRootId(pub u32); diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 478fae67c80..ad17f1730be 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -14,8 +14,9 @@ pub use crate::{ input::{ BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap, - DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, - SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData, + DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError, + ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult, + UniqueCrateData, }, }; use dashmap::{DashMap, mapref::entry::Entry}; @@ -33,7 +34,7 @@ pub type FxIndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>; #[macro_export] macro_rules! impl_intern_key { ($id:ident, $loc:ident) => { - #[salsa_macros::interned(no_lifetime)] + #[salsa_macros::interned(no_lifetime, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] pub struct $id { pub loc: $loc, @@ -43,7 +44,7 @@ macro_rules! impl_intern_key { impl ::std::fmt::Debug for $id { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { f.debug_tuple(stringify!($id)) - .field(&format_args!("{:04x}", self.0.as_u32())) + .field(&format_args!("{:04x}", self.0.index())) .finish() } } @@ -167,7 +168,7 @@ impl Files { } } -#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)] +#[salsa_macros::interned(no_lifetime, debug, constructor=from_span, revisions = usize::MAX)] #[derive(PartialOrd, Ord)] pub struct EditionedFileId { pub editioned_file_id: span::EditionedFileId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 85bd193223f..51612f341a1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -93,7 +93,7 @@ pub type TypeSource = InFile<TypePtr>; pub type LifetimePtr = AstPtr<ast::Lifetime>; pub type LifetimeSource = InFile<LifetimePtr>; -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct ExpressionStore { pub exprs: Arena<Expr>, pub pats: Arena<Pat>, @@ -114,7 +114,7 @@ pub struct ExpressionStore { ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>, } -#[derive(Debug, Eq, PartialEq, Default)] +#[derive(Debug, Eq, Default)] pub struct ExpressionStoreSourceMap { // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). @@ -127,19 +127,20 @@ pub struct ExpressionStoreSourceMap { label_map: FxHashMap<LabelSource, LabelId>, label_map_back: ArenaMap<LabelId, LabelSource>, - binding_definitions: FxHashMap<BindingId, SmallVec<[PatId; 4]>>, - - /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). - /// Instead, we use id of expression (`92`) to identify the field. - field_map_back: FxHashMap<ExprId, FieldSource>, - pat_field_map_back: FxHashMap<PatId, PatFieldSource>, - types_map_back: ArenaMap<TypeRefId, TypeSource>, types_map: FxHashMap<TypeSource, TypeRefId>, lifetime_map_back: ArenaMap<LifetimeRefId, LifetimeSource>, lifetime_map: FxHashMap<LifetimeSource, LifetimeRefId>, + binding_definitions: + ArenaMap<BindingId, SmallVec<[PatId; 2 * size_of::<usize>() / size_of::<PatId>()]>>, + + /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). + /// Instead, we use id of expression (`92`) to identify the field. + field_map_back: FxHashMap<ExprId, FieldSource>, + pat_field_map_back: FxHashMap<PatId, PatFieldSource>, + template_map: Option<Box<FormatTemplate>>, pub expansions: FxHashMap<InFile<MacroCallPtr>, MacroCallId>, @@ -149,6 +150,43 @@ pub struct ExpressionStoreSourceMap { pub diagnostics: Vec<ExpressionStoreDiagnostics>, } +impl PartialEq for ExpressionStoreSourceMap { + fn eq(&self, other: &Self) -> bool { + // we only need to compare one of the two mappings + // as the other is a reverse mapping and thus will compare + // the same as normal mapping + let Self { + expr_map: _, + expr_map_back, + pat_map: _, + pat_map_back, + label_map: _, + label_map_back, + types_map_back, + types_map: _, + lifetime_map_back, + lifetime_map: _, + // If this changed, our pattern data must have changed + binding_definitions: _, + // If this changed, our expression data must have changed + field_map_back: _, + // If this changed, our pattern data must have changed + pat_field_map_back: _, + template_map, + expansions, + diagnostics, + } = self; + *expr_map_back == other.expr_map_back + && *pat_map_back == other.pat_map_back + && *label_map_back == other.label_map_back + && *types_map_back == other.types_map_back + && *lifetime_map_back == other.lifetime_map_back + && *template_map == other.template_map + && *expansions == other.expansions + && *diagnostics == other.diagnostics + } +} + /// The body of an item (function, const etc.). #[derive(Debug, Eq, PartialEq, Default)] pub struct ExpressionStoreBuilder { @@ -698,7 +736,7 @@ impl ExpressionStoreSourceMap { } pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] { - self.binding_definitions.get(&binding).map_or(&[], Deref::deref) + self.binding_definitions.get(binding).map_or(&[], Deref::deref) } pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/path.rs index db83e73a0b9..19c7ce0ce04 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/path.rs @@ -29,8 +29,8 @@ pub enum Path { // This type is being used a lot, make sure it doesn't grow unintentionally. #[cfg(target_arch = "x86_64")] const _: () = { - assert!(size_of::<Path>() == 16); - assert!(size_of::<Option<Path>>() == 16); + assert!(size_of::<Path>() == 24); + assert!(size_of::<Option<Path>>() == 24); }; #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs index a46711c67e8..2dd0b9bdb86 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs @@ -535,7 +535,7 @@ fn foo() { let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); let pat_src = source_map - .pat_syntax(*source_map.binding_definitions[&resolved.binding()].first().unwrap()) + .pat_syntax(*source_map.binding_definitions[resolved.binding()].first().unwrap()) .unwrap(); let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax()); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs index eb3b92d31f1..eacc3f3cedf 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs @@ -149,7 +149,7 @@ pub enum TypeRef { } #[cfg(target_arch = "x86_64")] -const _: () = assert!(size_of::<TypeRef>() == 16); +const _: () = assert!(size_of::<TypeRef>() == 24); pub type TypeRefId = Idx<TypeRef>; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs index 777953d3f21..0013c2a2567 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -746,3 +746,83 @@ struct Struct9<#[pointee] T, U>(T) where T: ?Sized; 623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]], ); } + +#[test] +fn union_derive() { + check_errors( + r#" +//- minicore: clone, copy, default, fmt, hash, ord, eq, derive + +#[derive(Copy)] +union Foo1 { _v: () } +#[derive(Clone)] +union Foo2 { _v: () } +#[derive(Default)] +union Foo3 { _v: () } +#[derive(Debug)] +union Foo4 { _v: () } +#[derive(Hash)] +union Foo5 { _v: () } +#[derive(Ord)] +union Foo6 { _v: () } +#[derive(PartialOrd)] +union Foo7 { _v: () } +#[derive(Eq)] +union Foo8 { _v: () } +#[derive(PartialEq)] +union Foo9 { _v: () } + "#, + expect![[r#" + 78..118: this trait cannot be derived for unions + 119..157: this trait cannot be derived for unions + 158..195: this trait cannot be derived for unions + 196..232: this trait cannot be derived for unions + 233..276: this trait cannot be derived for unions + 313..355: this trait cannot be derived for unions"#]], + ); +} + +#[test] +fn default_enum_without_default_attr() { + check_errors( + r#" +//- minicore: default, derive + +#[derive(Default)] +enum Foo { + Bar, +} + "#, + expect!["1..41: `#[derive(Default)]` on enum with no `#[default]`"], + ); +} + +#[test] +fn generic_enum_default() { + check( + r#" +//- minicore: default, derive + +#[derive(Default)] +enum Foo<T> { + Bar(T), + #[default] + Baz, +} +"#, + expect![[r#" + +#[derive(Default)] +enum Foo<T> { + Bar(T), + #[default] + Baz, +} + +impl <T, > $crate::default::Default for Foo<T, > where { + fn default() -> Self { + Foo::Baz + } +}"#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs index ba75dca3d3d..338851b715b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs @@ -172,7 +172,7 @@ fn no() {} "ast_id_map_shim", "parse_shim", "real_span_map_shim", - "of_", + "EnumVariants::of_", ] "#]], expect![[r#" @@ -181,7 +181,7 @@ fn no() {} "ast_id_map_shim", "file_item_tree_query", "real_span_map_shim", - "of_", + "EnumVariants::of_", ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index d135584a080..15e68ff95cd 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -458,6 +458,7 @@ fn expand_simple_derive( invoc_span: Span, tt: &tt::TopSubtree, trait_path: tt::TopSubtree, + allow_unions: bool, make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let info = match parse_adt(db, tt, invoc_span) { @@ -469,6 +470,12 @@ fn expand_simple_derive( ); } }; + if !allow_unions && matches!(info.shape, AdtShape::Union) { + return ExpandResult::new( + tt::TopSubtree::empty(tt::DelimSpan::from_single(invoc_span)), + ExpandError::other(invoc_span, "this trait cannot be derived for unions"), + ); + } ExpandResult::ok(expand_simple_derive_with_parsed( invoc_span, info, @@ -535,7 +542,14 @@ fn copy_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) + expand_simple_derive( + db, + span, + tt, + quote! {span => #krate::marker::Copy }, + true, + |_| quote! {span =>}, + ) } fn clone_expand( @@ -544,7 +558,7 @@ fn clone_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, true, |adt| { if matches!(adt.shape, AdtShape::Union) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; return quote! {span => @@ -599,41 +613,63 @@ fn default_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::default::Default }, |adt| { - let body = match &adt.shape { - AdtShape::Struct(fields) => { - let name = &adt.name; - fields.as_pattern_map( - quote!(span =>#name), + let adt = match parse_adt(db, tt, span) { + Ok(info) => info, + Err(e) => { + return ExpandResult::new( + tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span }), + e, + ); + } + }; + let (body, constrain_to_trait) = match &adt.shape { + AdtShape::Struct(fields) => { + let name = &adt.name; + let body = fields.as_pattern_map( + quote!(span =>#name), + span, + |_| quote!(span =>#krate::default::Default::default()), + ); + (body, true) + } + AdtShape::Enum { default_variant, variants } => { + if let Some(d) = default_variant { + let (name, fields) = &variants[*d]; + let adt_name = &adt.name; + let body = fields.as_pattern_map( + quote!(span =>#adt_name :: #name), span, |_| quote!(span =>#krate::default::Default::default()), - ) + ); + (body, false) + } else { + return ExpandResult::new( + tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), + ExpandError::other(span, "`#[derive(Default)]` on enum with no `#[default]`"), + ); } - AdtShape::Enum { default_variant, variants } => { - if let Some(d) = default_variant { - let (name, fields) = &variants[*d]; - let adt_name = &adt.name; - fields.as_pattern_map( - quote!(span =>#adt_name :: #name), - span, - |_| quote!(span =>#krate::default::Default::default()), - ) - } else { - // FIXME: Return expand error here - quote!(span =>) + } + AdtShape::Union => { + return ExpandResult::new( + tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), + ExpandError::other(span, "this trait cannot be derived for unions"), + ); + } + }; + ExpandResult::ok(expand_simple_derive_with_parsed( + span, + adt, + quote! {span => #krate::default::Default }, + |_adt| { + quote! {span => + fn default() -> Self { + #body } } - AdtShape::Union => { - // FIXME: Return expand error here - quote!(span =>) - } - }; - quote! {span => - fn default() -> Self { - #body - } - } - }) + }, + constrain_to_trait, + tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), + )) } fn debug_expand( @@ -642,7 +678,7 @@ fn debug_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, false, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { let for_fields = fields.iter().map(|it| { @@ -697,10 +733,7 @@ fn debug_expand( } }) .collect(), - AdtShape::Union => { - // FIXME: Return expand error here - vec![] - } + AdtShape::Union => unreachable!(), }; quote! {span => fn fmt(&self, f: &mut #krate::fmt::Formatter) -> #krate::fmt::Result { @@ -718,11 +751,7 @@ fn hash_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, |adt| { - if matches!(adt.shape, AdtShape::Union) { - // FIXME: Return expand error here - return quote! {span =>}; - } + expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, false, |adt| { if matches!(&adt.shape, AdtShape::Enum { variants, .. } if variants.is_empty()) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; return quote! {span => @@ -769,7 +798,14 @@ fn eq_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) + expand_simple_derive( + db, + span, + tt, + quote! {span => #krate::cmp::Eq }, + true, + |_| quote! {span =>}, + ) } fn partial_eq_expand( @@ -778,11 +814,7 @@ fn partial_eq_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| { - if matches!(adt.shape, AdtShape::Union) { - // FIXME: Return expand error here - return quote! {span =>}; - } + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, false, |adt| { let name = &adt.name; let (self_patterns, other_patterns) = self_and_other_patterns(adt, name, span); @@ -854,7 +886,7 @@ fn ord_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, false, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -873,10 +905,6 @@ fn ord_expand( } } } - if matches!(adt.shape, AdtShape::Union) { - // FIXME: Return expand error here - return quote!(span =>); - } let (self_patterns, other_patterns) = self_and_other_patterns(adt, &adt.name, span); let arms = izip!(self_patterns, other_patterns, adt.shape.field_names(span)).map( |(pat1, pat2, fields)| { @@ -916,7 +944,7 @@ fn partial_ord_expand( tt: &tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, false, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -935,10 +963,6 @@ fn partial_ord_expand( } } } - if matches!(adt.shape, AdtShape::Union) { - // FIXME: Return expand error here - return quote!(span =>); - } let left = quote!(span =>#krate::intrinsics::discriminant_value(self)); let right = quote!(span =>#krate::intrinsics::discriminant_value(other)); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index f9abe4f5566..800b40a9e7e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -7,6 +7,7 @@ use intern::{ Symbol, sym::{self}, }; +use itertools::Itertools; use mbe::{DelimiterKind, expect_fragment}; use span::{Edition, FileId, Span}; use stdx::format_to; @@ -681,11 +682,19 @@ fn relative_file( } fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> { - let delimiter = tt.top_subtree().delimiter; - tt.iter() - .next() - .ok_or(delimiter.open.cover(delimiter.close)) - .and_then(|tt| match tt { + let mut tt = TtElement::Subtree(tt.top_subtree(), tt.iter()); + (|| { + // FIXME: We wrap expression fragments in parentheses which can break this expectation + // here + // Remove this once we handle none delims correctly + while let TtElement::Subtree(sub, tt_iter) = &mut tt + && let DelimiterKind::Parenthesis | DelimiterKind::Invisible = sub.delimiter.kind + { + tt = + tt_iter.exactly_one().map_err(|_| sub.delimiter.open.cover(sub.delimiter.close))?; + } + + match tt { TtElement::Leaf(tt::Leaf::Literal(tt::Literal { symbol: text, span, @@ -698,35 +707,11 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> { kind: tt::LitKind::StrRaw(_), suffix: _, })) => Ok((text.clone(), *span)), - // FIXME: We wrap expression fragments in parentheses which can break this expectation - // here - // Remove this once we handle none delims correctly - TtElement::Subtree(tt, mut tt_iter) - if tt.delimiter.kind == DelimiterKind::Parenthesis => - { - tt_iter - .next() - .and_then(|tt| match tt { - TtElement::Leaf(tt::Leaf::Literal(tt::Literal { - symbol: text, - span, - kind: tt::LitKind::Str, - suffix: _, - })) => Some((unescape_symbol(text), *span)), - TtElement::Leaf(tt::Leaf::Literal(tt::Literal { - symbol: text, - span, - kind: tt::LitKind::StrRaw(_), - suffix: _, - })) => Some((text.clone(), *span)), - _ => None, - }) - .ok_or(delimiter.open.cover(delimiter.close)) - } TtElement::Leaf(l) => Err(*l.span()), TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)), - }) - .map_err(|span| ExpandError::other(span, "expected string literal")) + } + })() + .map_err(|span| ExpandError::other(span, "expected string literal")) } fn include_expand( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 7e9928c41ff..888c1405a6b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -145,7 +145,7 @@ pub trait ExpandDatabase: RootQueryDb { fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext; } -#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext)] +#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext, revisions = usize::MAX)] pub struct SyntaxContextWrapper { pub data: SyntaxContext, } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index a73a22370d2..6730b337d35 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -315,11 +315,11 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> { } /// Falls back to the macro call range if the node cannot be mapped up fully. - pub fn original_file_range_with_macro_call_body( + pub fn original_file_range_with_macro_call_input( self, db: &dyn db::ExpandDatabase, ) -> FileRange { - self.borrow().map(SyntaxNode::text_range).original_node_file_range_with_macro_call_body(db) + self.borrow().map(SyntaxNode::text_range).original_node_file_range_with_macro_call_input(db) } pub fn original_syntax_node_rooted( @@ -465,7 +465,7 @@ impl InFile<TextRange> { } } - pub fn original_node_file_range_with_macro_call_body( + pub fn original_node_file_range_with_macro_call_input( self, db: &dyn db::ExpandDatabase, ) -> FileRange { @@ -476,7 +476,7 @@ impl InFile<TextRange> { Some(it) => it, _ => { let loc = db.lookup_intern_macro_call(mac_file); - loc.kind.original_call_range_with_body(db) + loc.kind.original_call_range_with_input(db) } } } @@ -497,6 +497,18 @@ impl InFile<TextRange> { } } } + + pub fn original_node_file_range_rooted_opt( + self, + db: &dyn db::ExpandDatabase, + ) -> Option<FileRange> { + match self.file_id { + HirFileId::FileId(file_id) => Some(FileRange { file_id, range: self.value }), + HirFileId::MacroFile(mac_file) => { + map_node_range_up_rooted(db, &db.expansion_span_map(mac_file), self.value) + } + } + } } impl<N: AstNode> InFile<N> { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 6ecac1463f5..ac61b220097 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -199,9 +199,9 @@ impl ExpandErrorKind { }, &ExpandErrorKind::MissingProcMacroExpander(def_crate) => { match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) { - Some((e, hard_err)) => RenderedExpandError { - message: e.to_owned(), - error: hard_err, + Some(e) => RenderedExpandError { + message: e.to_string(), + error: e.is_hard_error(), kind: RenderedExpandError::GENERAL_KIND, }, None => RenderedExpandError { @@ -688,8 +688,11 @@ impl MacroCallKind { /// Returns the original file range that best describes the location of this macro call. /// - /// Unlike `MacroCallKind::original_call_range`, this also spans the item of attributes and derives. - pub fn original_call_range_with_body(self, db: &dyn ExpandDatabase) -> FileRange { + /// This spans the entire macro call, including its input. That is for + /// - fn_like! {}, it spans the path and token tree + /// - #\[derive], it spans the `#[derive(...)]` attribute and the annotated item + /// - #\[attr], it spans the `#[attr(...)]` attribute and the annotated item + pub fn original_call_range_with_input(self, db: &dyn ExpandDatabase) -> FileRange { let mut kind = self; let file_id = loop { match kind.file_id() { @@ -712,8 +715,8 @@ impl MacroCallKind { /// Returns the original file range that best describes the location of this macro call. /// /// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros - /// get the whole `ast::MacroCall`, attribute macros get the attribute's range, and derives - /// get only the specific derive that is being referred to. + /// get the macro path (rustc shows the whole `ast::MacroCall`), attribute macros get the + /// attribute's range, and derives get only the specific derive that is being referred to. pub fn original_call_range(self, db: &dyn ExpandDatabase) -> FileRange { let mut kind = self; let file_id = loop { @@ -726,7 +729,14 @@ impl MacroCallKind { }; let range = match kind { - MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(), + MacroCallKind::FnLike { ast_id, .. } => { + let node = ast_id.to_node(db); + node.path() + .unwrap() + .syntax() + .text_range() + .cover(node.excl_token().unwrap().text_range()) + } MacroCallKind::Derive { ast_id, derive_attr_index, .. } => { // FIXME: should be the range of the macro name, not the whole derive // FIXME: handle `cfg_attr` @@ -1056,7 +1066,7 @@ impl ExpandTo { intern::impl_internable!(ModPath, attrs::AttrInput); -#[salsa_macros::interned(no_lifetime, debug)] +#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)] #[doc(alias = "MacroFileId")] pub struct MacroCallId { pub loc: MacroCallLoc, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 217d991d110..679f61112ad 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -179,9 +179,10 @@ impl Name { self.symbol.as_str() } + #[inline] pub fn display<'a>( &'a self, - db: &dyn crate::db::ExpandDatabase, + db: &dyn salsa::Database, edition: Edition, ) -> impl fmt::Display + 'a { _ = db; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs index 6134c3a36b9..6431d46d39e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/prettify_macro_expansion_.rs @@ -46,7 +46,7 @@ pub fn prettify_macro_expansion( } else if let Some(crate_name) = ¯o_def_crate.extra_data(db).display_name { make::tokens::ident(crate_name.crate_name().as_str()) } else { - return dollar_crate.clone(); + dollar_crate.clone() } }); if replacement.text() == "$crate" { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs index 1c8ebb6f535..f97d721dfa8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs @@ -4,7 +4,7 @@ use core::fmt; use std::any::Any; use std::{panic::RefUnwindSafe, sync}; -use base_db::{Crate, CrateBuilderId, CratesIdMap, Env}; +use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError}; use intern::Symbol; use rustc_hash::FxHashMap; use span::Span; @@ -53,8 +53,8 @@ pub enum ProcMacroExpansionError { System(String), } -pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, (String, bool)>; -type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, (Box<str>, bool)>; +pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, ProcMacroLoadingError>; +type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, ProcMacroLoadingError>; #[derive(Default, Debug)] pub struct ProcMacrosBuilder(FxHashMap<CrateBuilderId, Arc<CrateProcMacros>>); @@ -77,9 +77,7 @@ impl ProcMacrosBuilder { proc_macros_crate, match proc_macro { Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))), - Err((e, hard_err)) => { - Arc::new(CrateProcMacros(Err((e.into_boxed_str(), hard_err)))) - } + Err(e) => Arc::new(CrateProcMacros(Err(e))), }, ); } @@ -139,8 +137,8 @@ impl CrateProcMacros { ) } - pub fn get_error(&self) -> Option<(&str, bool)> { - self.0.as_ref().err().map(|(e, hard_err)| (&**e, *hard_err)) + pub fn get_error(&self) -> Option<&ProcMacroLoadingError> { + self.0.as_ref().err() } /// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 1029969992c..5d3be07f3db 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -237,15 +237,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { // Interned IDs for Chalk integration #[salsa::interned] - fn intern_type_or_const_param_id( - &self, - param_id: TypeOrConstParamId, - ) -> InternedTypeOrConstParamId; - - #[salsa::interned] - fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId; - - #[salsa::interned] fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; #[salsa::interned] @@ -282,9 +273,8 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(crate::variance::variances_of)] #[salsa::cycle( - // cycle_fn = crate::variance::variances_of_cycle_fn, - // cycle_initial = crate::variance::variances_of_cycle_initial, - cycle_result = crate::variance::variances_of_cycle_initial, + cycle_fn = crate::variance::variances_of_cycle_fn, + cycle_initial = crate::variance::variances_of_cycle_initial, )] fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>; @@ -329,9 +319,31 @@ fn hir_database_is_dyn_compatible() { fn _assert_dyn_compatible(_: &dyn HirDatabase) {} } -impl_intern_key!(InternedTypeOrConstParamId, TypeOrConstParamId); +#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)] +#[derive(PartialOrd, Ord)] +pub struct InternedTypeOrConstParamId { + pub loc: TypeOrConstParamId, +} +impl ::std::fmt::Debug for InternedTypeOrConstParamId { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + f.debug_tuple(stringify!(InternedTypeOrConstParamId)) + .field(&format_args!("{:04x}", self.0.index())) + .finish() + } +} -impl_intern_key!(InternedLifetimeParamId, LifetimeParamId); +#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)] +#[derive(PartialOrd, Ord)] +pub struct InternedLifetimeParamId { + pub loc: LifetimeParamId, +} +impl ::std::fmt::Debug for InternedLifetimeParamId { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + f.debug_tuple(stringify!(InternedLifetimeParamId)) + .field(&format_args!("{:04x}", self.0.index())) + .finish() + } +} impl_intern_key!(InternedConstParamId, ConstParamId); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index 0bce32a6778..c3ab5aff3db 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs @@ -25,7 +25,6 @@ use crate::{ db::HirDatabase, display::{HirDisplay, HirDisplayError, HirFormatter}, infer::BindingMode, - lang_items::is_box, }; use self::pat_util::EnumerateAndAdjustIterator; @@ -77,7 +76,7 @@ pub(crate) enum PatKind { subpatterns: Vec<FieldPat>, }, - /// `box P`, `&P`, `&mut P`, etc. + /// `&P`, `&mut P`, etc. Deref { subpattern: Pat, }, @@ -406,7 +405,6 @@ impl HirDisplay for Pat { } PatKind::Deref { subpattern } => { match self.ty.kind(Interner) { - TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?, &TyKind::Ref(mutbl, ..) => { write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })? } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 7cf22c64d0f..22b7f5ac9fd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -21,7 +21,7 @@ use crate::{ inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from}, }; -use super::{FieldPat, Pat, PatKind, is_box}; +use super::{FieldPat, Pat, PatKind}; use Constructor::*; @@ -170,8 +170,6 @@ impl<'db> MatchCheckCtx<'db> { } PatKind::Deref { subpattern } => { ctor = match pat.ty.kind(Interner) { - // This is a box pattern. - TyKind::Adt(adt, _) if is_box(self.db, adt.0) => Struct, TyKind::Ref(..) => Ref, _ => { never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty); @@ -194,23 +192,6 @@ impl<'db> MatchCheckCtx<'db> { ctor = Struct; arity = substs.len(Interner); } - TyKind::Adt(adt, _) if is_box(self.db, adt.0) => { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, - // _)` or a box pattern. As a hack to avoid an ICE with the former, we - // ignore other fields than the first one. This will trigger an error later - // anyway. - // See https://github.com/rust-lang/rust/issues/82772 , - // explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977 - // The problem is that we can't know from the type whether we'll match - // normally or through box-patterns. We'll have to figure out a proper - // solution when we introduce generalized deref patterns. Also need to - // prevent mixing of those two options. - fields.retain(|ipat| ipat.idx == 0); - ctor = Struct; - arity = 1; - } &TyKind::Adt(AdtId(adt), _) => { ctor = match pat.kind.as_ref() { PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => { @@ -277,12 +258,6 @@ impl<'db> MatchCheckCtx<'db> { }) .collect(), }, - TyKind::Adt(adt, _) if is_box(self.db, adt.0) => { - // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside - // of `std`). So this branch is only reachable when the feature is enabled and - // the pattern is a box pattern. - PatKind::Deref { subpattern: subpatterns.next().unwrap() } - } TyKind::Adt(adt, substs) => { let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap(); let subpatterns = self @@ -343,14 +318,8 @@ impl PatCx for MatchCheckCtx<'_> { Struct | Variant(_) | UnionField => match *ty.kind(Interner) { TyKind::Tuple(arity, ..) => arity, TyKind::Adt(AdtId(adt), ..) => { - if is_box(self.db, adt) { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - 1 - } else { - let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap(); - variant.fields(self.db).fields().len() - } + let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap(); + variant.fields(self.db).fields().len() } _ => { never!("Unexpected type for `Single` constructor: {:?}", ty); @@ -383,29 +352,22 @@ impl PatCx for MatchCheckCtx<'_> { tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect() } TyKind::Ref(.., rty) => single(rty.clone()), - &TyKind::Adt(AdtId(adt), ref substs) => { - if is_box(self.db, adt) { - // The only legal patterns of type `Box` (outside `std`) are `_` and box - // patterns. If we're here we can assume this is a box pattern. - let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone(); - single(subst_ty) - } else { - let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap(); - - let visibilities = LazyCell::new(|| self.db.field_visibilities(variant)); - - self.list_variant_fields(ty, variant) - .map(move |(fid, ty)| { - let is_visible = || { - matches!(adt, hir_def::AdtId::EnumId(..)) - || visibilities[fid].is_visible_from(self.db, self.module) - }; - let is_uninhabited = self.is_uninhabited(&ty); - let private_uninhabited = is_uninhabited && !is_visible(); - (ty, PrivateUninhabitedField(private_uninhabited)) - }) - .collect() - } + &TyKind::Adt(AdtId(adt), ..) => { + let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap(); + + let visibilities = LazyCell::new(|| self.db.field_visibilities(variant)); + + self.list_variant_fields(ty, variant) + .map(move |(fid, ty)| { + let is_visible = || { + matches!(adt, hir_def::AdtId::EnumId(..)) + || visibilities[fid].is_visible_from(self.db, self.module) + }; + let is_uninhabited = self.is_uninhabited(&ty); + let private_uninhabited = is_uninhabited && !is_visible(); + (ty, PrivateUninhabitedField(private_uninhabited)) + }) + .collect() } ty_kind => { never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 507bab29208..810fe76f231 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1432,10 +1432,10 @@ impl HirDisplay for Ty { match f.closure_style { ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"), ClosureStyle::ClosureWithId => { - return write!(f, "{{closure#{:?}}}", id.0.as_u32()); + return write!(f, "{{closure#{:?}}}", id.0.index()); } ClosureStyle::ClosureWithSubst => { - write!(f, "{{closure#{:?}}}", id.0.as_u32())?; + write!(f, "{{closure#{:?}}}", id.0.index())?; return hir_fmt_generics(f, substs.as_slice(Interner), None, None); } _ => (), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index ce53198e966..e880438e3a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -460,19 +460,17 @@ pub struct InferenceResult { /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of /// that which allows us to resolve a [`TupleFieldId`]s type. - pub tuple_field_access_types: FxHashMap<TupleId, Substitution>, + tuple_field_access_types: FxHashMap<TupleId, Substitution>, /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead. - pub diagnostics: Vec<InferenceDiagnostic>, - pub type_of_expr: ArenaMap<ExprId, Ty>, + diagnostics: Vec<InferenceDiagnostic>, + pub(crate) type_of_expr: ArenaMap<ExprId, Ty>, /// For each pattern record the type it resolves to. /// /// **Note**: When a pattern type is resolved it may still contain /// unresolved or missing subpatterns or subpatterns of mismatched types. - pub type_of_pat: ArenaMap<PatId, Ty>, - pub type_of_binding: ArenaMap<BindingId, Ty>, - pub type_of_rpit: ArenaMap<ImplTraitIdx, Ty>, - /// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop. - pub type_of_for_iterator: FxHashMap<ExprId, Ty>, + pub(crate) type_of_pat: ArenaMap<PatId, Ty>, + pub(crate) type_of_binding: ArenaMap<BindingId, Ty>, + pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx, Ty>, type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>, /// Whether there are any type-mismatching errors in the result. // FIXME: This isn't as useful as initially thought due to us falling back placeholders to @@ -483,7 +481,7 @@ pub struct InferenceResult { // FIXME: Move this into `InferenceContext` standard_types: InternedStandardTypes, /// Stores the types which were implicitly dereferenced in pattern binding modes. - pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>, + pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty>>, /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings. /// /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an @@ -497,12 +495,12 @@ pub struct InferenceResult { /// } /// ``` /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`. - pub binding_modes: ArenaMap<PatId, BindingMode>, - pub expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>, + pub(crate) binding_modes: ArenaMap<PatId, BindingMode>, + pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>, pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>, // FIXME: remove this field pub mutated_bindings_in_closure: FxHashSet<BindingId>, - pub coercion_casts: FxHashSet<ExprId>, + pub(crate) coercion_casts: FxHashSet<ExprId>, } impl InferenceResult { @@ -566,6 +564,26 @@ impl InferenceResult { pub fn is_erroneous(&self) -> bool { self.has_errors && self.type_of_expr.iter().count() == 0 } + + pub fn diagnostics(&self) -> &[InferenceDiagnostic] { + &self.diagnostics + } + + pub fn tuple_field_access_type(&self, id: TupleId) -> &Substitution { + &self.tuple_field_access_types[&id] + } + + pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty]> { + self.pat_adjustments.get(&id).map(|it| &**it) + } + + pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> { + self.expr_adjustments.get(&id).map(|it| &**it) + } + + pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> { + self.binding_modes.get(id).copied() + } } impl Index<ExprId> for InferenceResult { @@ -772,7 +790,6 @@ impl<'db> InferenceContext<'db> { type_of_pat, type_of_binding, type_of_rpit, - type_of_for_iterator, type_mismatches, has_errors, standard_types: _, @@ -832,11 +849,6 @@ impl<'db> InferenceContext<'db> { *has_errors = *has_errors || ty.contains_unknown(); } type_of_rpit.shrink_to_fit(); - for ty in type_of_for_iterator.values_mut() { - *ty = table.resolve_completely(ty.clone()); - *has_errors = *has_errors || ty.contains_unknown(); - } - type_of_for_iterator.shrink_to_fit(); *has_errors |= !type_mismatches.is_empty(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 65a273cdf8d..c3029bf2b59 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -1229,10 +1229,11 @@ impl InferenceContext<'_> { self.select_from_expr(*expr); } } - Expr::Let { pat: _, expr } => { + Expr::Let { pat, expr } => { self.walk_expr(*expr); - let place = self.place_of_expr(*expr); - self.ref_expr(*expr, place); + if let Some(place) = self.place_of_expr(*expr) { + self.consume_with_pat(place, *pat); + } } Expr::UnaryOp { expr, op: _ } | Expr::Array(Array::Repeat { initializer: expr, repeat: _ }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index d40d52c134d..d43c99fc282 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -731,9 +731,32 @@ impl InferenceContext<'_> { &Pat::Expr(expr) => { Some(self.infer_expr(expr, &Expectation::none(), ExprIsRead::No)) } - Pat::Path(path) => Some(self.infer_expr_path(path, target.into(), tgt_expr)), + Pat::Path(path) => { + let resolver_guard = + self.resolver.update_to_inner_scope(self.db, self.owner, tgt_expr); + let resolution = self.resolver.resolve_path_in_value_ns_fully( + self.db, + path, + self.body.pat_path_hygiene(target), + ); + self.resolver.reset_to_guard(resolver_guard); + + if matches!( + resolution, + Some( + ValueNs::ConstId(_) + | ValueNs::StructId(_) + | ValueNs::EnumVariantId(_) + ) + ) { + None + } else { + Some(self.infer_expr_path(path, target.into(), tgt_expr)) + } + } _ => None, }; + let is_destructuring_assignment = lhs_ty.is_none(); if let Some(lhs_ty) = lhs_ty { self.write_pat_ty(target, lhs_ty.clone()); @@ -747,7 +770,15 @@ impl InferenceContext<'_> { self.inside_assignment = false; self.resolver.reset_to_guard(resolver_guard); } - self.result.standard_types.unit.clone() + if is_destructuring_assignment && self.diverges.is_always() { + // Ordinary assignments always return `()`, even when they diverge. + // However, rustc lowers destructuring assignments into blocks, and blocks return `!` if they have no tail + // expression and they diverge. Therefore, we have to do the same here, even though we don't lower destructuring + // assignments into blocks. + self.table.new_maybe_never_var() + } else { + self.result.standard_types.unit.clone() + } } Expr::Range { lhs, rhs, range_type } => { let lhs_ty = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 3fa2bfbd1b7..107da6a5af6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -261,7 +261,7 @@ pub fn layout_of_ty_query( } // Potentially-wide pointers. TyKind::Ref(_, _, pointee) | TyKind::Raw(_, pointee) => { - let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); + let mut data_ptr = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO)); if matches!(ty.kind(Interner), TyKind::Ref(..)) { data_ptr.valid_range_mut().start = 1; } @@ -285,7 +285,7 @@ pub fn layout_of_ty_query( scalar_unit(dl, Primitive::Int(dl.ptr_sized_integer(), false)) } TyKind::Dyn(..) => { - let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::DATA)); + let mut vtable = scalar_unit(dl, Primitive::Pointer(AddressSpace::ZERO)); vtable.valid_range_mut().start = 1; vtable } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs index e1e1c44996c..88c33ecccad 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs @@ -2,7 +2,7 @@ use base_db::Crate; use hir_def::layout::TargetDataLayout; -use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; +use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors, AddressSpace}; use triomphe::Arc; use crate::db::HirDatabase; @@ -12,7 +12,7 @@ pub fn target_data_layout_query( krate: Crate, ) -> Result<Arc<TargetDataLayout>, Arc<str>> { match &krate.workspace_data(db).data_layout { - Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) { + Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) { Ok(it) => Ok(Arc::new(it)), Err(e) => { Err(match e { @@ -39,6 +39,7 @@ pub fn target_data_layout_query( target, } => format!(r#"inconsistent target specification: "data-layout" claims pointers are {pointer_size}-bit, while "target-pointer-width" is `{target}`"#), TargetDataLayoutErrors::InvalidBitsSize { err } => err, + TargetDataLayoutErrors::UnknownPointerSpecification { err } => format!(r#"use of unknown pointer specifer in "data-layout": {err}"#), }.into()) } }, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs index 6936d8193eb..9d3d2044c43 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs @@ -13,7 +13,8 @@ use salsa::{ use crate::{ AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId, - PlaceholderIndex, chalk_db, db::HirDatabase, + PlaceholderIndex, chalk_db, + db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId}, }; pub trait ToChalk { @@ -125,30 +126,32 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) }); - db.lookup_intern_type_or_const_param_id(interned_id) + let interned_id = + InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) }); + interned_id.loc(db) } pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex { - let interned_id = db.intern_type_or_const_param_id(id); + let interned_id = InternedTypeOrConstParamId::new(db, id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, - idx: interned_id.as_id().as_u32() as usize, + idx: interned_id.as_id().index() as usize, } } pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId { assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) }); - db.lookup_intern_lifetime_param_id(interned_id) + let interned_id = + InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) }); + interned_id.loc(db) } pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex { - let interned_id = db.intern_lifetime_param_id(id); + let interned_id = InternedLifetimeParamId::new(db, id); PlaceholderIndex { ui: chalk_ir::UniverseIndex::ROOT, - idx: interned_id.as_id().as_u32() as usize, + idx: interned_id.as_id().index() as usize, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 1ec55a82092..55fada14363 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -630,7 +630,7 @@ impl Evaluator<'_> { Ok(target_data_layout) => target_data_layout, Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), }; - let cached_ptr_size = target_data_layout.pointer_size.bytes_usize(); + let cached_ptr_size = target_data_layout.pointer_size().bytes_usize(); Ok(Evaluator { target_data_layout, stack: vec![0], diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs index d049c678e2d..b5de0e52f5b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs @@ -166,10 +166,10 @@ impl TestDB { self.events.lock().unwrap().take().unwrap() } - pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { + pub(crate) fn log_executed(&self, f: impl FnOnce()) -> (Vec<String>, Vec<salsa::Event>) { let events = self.log(f); - events - .into_iter() + let executed = events + .iter() .filter_map(|e| match e.kind { // This is pretty horrible, but `Debug` is the only way to inspect // QueryDescriptor at the moment. @@ -181,6 +181,7 @@ impl TestDB { } _ => None, }) - .collect() + .collect(); + (executed, events) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 7fb981752de..dbc68eeba1e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -446,7 +446,7 @@ fn main() { } #[test] -fn let_binding_is_a_ref_capture() { +fn let_binding_is_a_ref_capture_in_ref_binding() { check_closure_captures( r#" //- minicore:copy @@ -454,12 +454,36 @@ struct S; fn main() { let mut s = S; let s_ref = &mut s; + let mut s2 = S; + let s_ref2 = &mut s2; let closure = || { if let ref cb = s_ref { + } else if let ref mut cb = s_ref2 { } }; } "#, - expect!["83..135;49..54;112..117 ByRef(Shared) s_ref &'? &'? mut S"], + expect![[r#" + 129..225;49..54;149..155 ByRef(Shared) s_ref &'? &'? mut S + 129..225;93..99;188..198 ByRef(Mut { kind: Default }) s_ref2 &'? mut &'? mut S"#]], + ); +} + +#[test] +fn let_binding_is_a_value_capture_in_binding() { + check_closure_captures( + r#" +//- minicore:copy, option +struct Box(i32); +fn main() { + let b = Some(Box(0)); + let closure = || { + if let Some(b) = b { + let _move = b; + } + }; +} +"#, + expect!["73..149;37..38;103..104 ByValue b Option<Box>"], ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index 0377ce95f19..3159499e867 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -1,6 +1,7 @@ use base_db::SourceDatabase; use expect_test::Expect; use hir_def::{DefWithBodyId, ModuleDefId}; +use salsa::EventKind; use test_fixture::WithFixture; use crate::{db::HirDatabase, test_db::TestDB}; @@ -567,11 +568,11 @@ fn main() { "ast_id_map_shim", "parse_shim", "real_span_map_shim", - "query_with_diagnostics_", + "TraitItems::query_with_diagnostics_", "body_shim", "body_with_source_map_shim", "attrs_shim", - "of_", + "ImplItems::of_", "infer_shim", "trait_signature_shim", "trait_signature_with_source_map_shim", @@ -596,8 +597,8 @@ fn main() { "struct_signature_with_source_map_shim", "generic_predicates_shim", "value_ty_shim", - "firewall_", - "query_", + "VariantFields::firewall_", + "VariantFields::query_", "lang_item", "inherent_impls_in_crate_shim", "impl_signature_shim", @@ -674,11 +675,11 @@ fn main() { "file_item_tree_query", "real_span_map_shim", "crate_local_def_map", - "query_with_diagnostics_", + "TraitItems::query_with_diagnostics_", "body_with_source_map_shim", "attrs_shim", "body_shim", - "of_", + "ImplItems::of_", "infer_shim", "attrs_shim", "trait_signature_with_source_map_shim", @@ -697,7 +698,7 @@ fn main() { "function_signature_with_source_map_shim", "expr_scopes_shim", "struct_signature_with_source_map_shim", - "query_", + "VariantFields::query_", "inherent_impls_in_crate_shim", "impl_signature_with_source_map_shim", "impl_signature_shim", @@ -718,10 +719,23 @@ fn execute_assert_events( required: &[(&str, usize)], expect: Expect, ) { - let events = db.log_executed(f); - for (event, count) in required { - let n = events.iter().filter(|it| it.contains(event)).count(); - assert_eq!(n, *count, "Expected {event} to be executed {count} times, but only got {n}"); - } - expect.assert_debug_eq(&events); + let (executed, events) = db.log_executed(f); + salsa::attach(db, || { + for (event, count) in required { + let n = executed.iter().filter(|it| it.contains(event)).count(); + assert_eq!( + n, + *count, + "Expected {event} to be executed {count} times, but only got {n}:\n \ + Executed: {executed:#?}\n \ + Event log: {events:#?}", + events = events + .iter() + .filter(|event| !matches!(event.kind, EventKind::WillCheckCancellation)) + .map(|event| { format!("{:?}", event.kind) }) + .collect::<Vec<_>>(), + ); + } + expect.assert_debug_eq(&executed); + }); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs index 1ca4c9b2ad5..6a9135622de 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs @@ -785,3 +785,31 @@ fn make_up_a_pointer<T>() -> *const T { "#]], ) } + +#[test] +fn diverging_destructuring_assignment() { + check_infer_with_mismatches( + r#" +fn foo() { + let n = match 42 { + 0 => _ = loop {}, + _ => 0, + }; +} + "#, + expect![[r#" + 9..84 '{ ... }; }': () + 19..20 'n': i32 + 23..81 'match ... }': i32 + 29..31 '42': i32 + 42..43 '0': i32 + 42..43 '0': i32 + 47..48 '_': ! + 47..58 '_ = loop {}': i32 + 51..58 'loop {}': ! + 56..58 '{}': () + 68..69 '_': i32 + 73..74 '0': i32 + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 43e8f3747ab..b154e598785 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -3751,7 +3751,7 @@ fn foo() { } let v: bool = true; m!(); - // ^^^^ i32 + // ^^ i32 } "#, ); @@ -3765,39 +3765,39 @@ fn foo() { let v: bool; macro_rules! m { () => { v } } m!(); - // ^^^^ bool + // ^^ bool let v: char; macro_rules! m { () => { v } } m!(); - // ^^^^ char + // ^^ char { let v: u8; macro_rules! m { () => { v } } m!(); - // ^^^^ u8 + // ^^ u8 let v: i8; macro_rules! m { () => { v } } m!(); - // ^^^^ i8 + // ^^ i8 let v: i16; macro_rules! m { () => { v } } m!(); - // ^^^^ i16 + // ^^ i16 { let v: u32; macro_rules! m { () => { v } } m!(); - // ^^^^ u32 + // ^^ u32 let v: u64; macro_rules! m { () => { v } } m!(); - // ^^^^ u64 + // ^^ u64 } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 08a215fecf6..87d9df611bd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -54,14 +54,14 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Ar variances.is_empty().not().then(|| Arc::from_iter(variances)) } -// pub(crate) fn variances_of_cycle_fn( -// _db: &dyn HirDatabase, -// _result: &Option<Arc<[Variance]>>, -// _count: u32, -// _def: GenericDefId, -// ) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> { -// salsa::CycleRecoveryAction::Iterate -// } +pub(crate) fn variances_of_cycle_fn( + _db: &dyn HirDatabase, + _result: &Option<Arc<[Variance]>>, + _count: u32, + _def: GenericDefId, +) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> { + salsa::CycleRecoveryAction::Iterate +} pub(crate) fn variances_of_cycle_initial( db: &dyn HirDatabase, @@ -965,7 +965,7 @@ struct S3<T>(S<T, T>); struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V); "#, expect![[r#" - FixedPoint[T: bivariant, U: bivariant, V: bivariant] + FixedPoint[T: covariant, U: covariant, V: covariant] "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index aba2e032b32..c1e814ec223 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -36,16 +36,16 @@ pub use hir_ty::{ }; macro_rules! diagnostics { - ($($diag:ident $(<$lt:lifetime>)?,)*) => { + ($AnyDiagnostic:ident <$db:lifetime> -> $($diag:ident $(<$lt:lifetime>)?,)*) => { #[derive(Debug)] - pub enum AnyDiagnostic<'db> {$( + pub enum $AnyDiagnostic<$db> {$( $diag(Box<$diag $(<$lt>)?>), )*} $( - impl<'db> From<$diag $(<$lt>)?> for AnyDiagnostic<'db> { - fn from(d: $diag $(<$lt>)?) -> AnyDiagnostic<'db> { - AnyDiagnostic::$diag(Box::new(d)) + impl<$db> From<$diag $(<$lt>)?> for $AnyDiagnostic<$db> { + fn from(d: $diag $(<$lt>)?) -> $AnyDiagnostic<$db> { + $AnyDiagnostic::$diag(Box::new(d)) } } )* @@ -66,7 +66,7 @@ macro_rules! diagnostics { // }, ... // ] -diagnostics![ +diagnostics![AnyDiagnostic<'db> -> AwaitOutsideOfAsync, BreakOutsideOfLoop, CastToUnsized<'db>, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index e8a18169712..5c6f622e6c3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1260,7 +1260,9 @@ impl TupleField { } pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { - let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple] + let ty = db + .infer(self.owner) + .tuple_field_access_type(self.tuple) .as_slice(Interner) .get(self.index as usize) .and_then(|arg| arg.ty(Interner)) @@ -1927,7 +1929,7 @@ impl DefWithBody { expr_store_diagnostics(db, acc, &source_map); let infer = db.infer(self.into()); - for d in &infer.diagnostics { + for d in infer.diagnostics() { acc.extend(AnyDiagnostic::inference_diagnostic( db, self.into(), diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index f18ca7cb201..0662bfddcf8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -254,7 +254,7 @@ impl<'db> SourceAnalyzer<'db> { // expressions nor patterns). let expr_id = self.expr_id(expr.clone())?.as_expr()?; let infer = self.infer()?; - infer.expr_adjustments.get(&expr_id).map(|v| &**v) + infer.expr_adjustment(expr_id) } pub(crate) fn type_of_type( @@ -286,7 +286,7 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; let coerced = expr_id .as_expr() - .and_then(|expr_id| infer.expr_adjustments.get(&expr_id)) + .and_then(|expr_id| infer.expr_adjustment(expr_id)) .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone())); let ty = infer[expr_id].clone(); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); @@ -302,12 +302,11 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; let coerced = match expr_or_pat_id { ExprOrPatId::ExprId(idx) => infer - .expr_adjustments - .get(&idx) + .expr_adjustment(idx) .and_then(|adjusts| adjusts.last().cloned()) .map(|adjust| adjust.target), ExprOrPatId::PatId(idx) => { - infer.pat_adjustments.get(&idx).and_then(|adjusts| adjusts.last().cloned()) + infer.pat_adjustment(idx).and_then(|adjusts| adjusts.last().cloned()) } }; @@ -345,7 +344,7 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option<BindingMode> { let id = self.pat_id(&pat.clone().into())?; let infer = self.infer()?; - infer.binding_modes.get(id.as_pat()?).map(|bm| match bm { + infer.binding_mode(id.as_pat()?).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { @@ -362,8 +361,7 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; Some( infer - .pat_adjustments - .get(&pat_id.as_pat()?)? + .pat_adjustment(pat_id.as_pat()?)? .iter() .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone())) .collect(), @@ -736,7 +734,7 @@ impl<'db> SourceAnalyzer<'db> { let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?; let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; - let (adt, subst) = self.infer()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?; + let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); Some(( @@ -765,7 +763,8 @@ impl<'db> SourceAnalyzer<'db> { }, }; - let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, Some(store))?; + let body_owner = self.resolver.body_owner(); + let res = resolve_hir_value_path(db, &self.resolver, body_owner, path, HygieneId::ROOT)?; match res { PathResolution::Def(def) => Some(def), _ => None, @@ -1249,7 +1248,7 @@ impl<'db> SourceAnalyzer<'db> { let infer = self.infer()?; let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?; - let substs = infer.type_of_pat[pat_id].as_adt()?.1; + let substs = infer[pat_id].as_adt()?.1; let (variant, missing_fields, _exhaustive) = record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; @@ -1785,8 +1784,8 @@ pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> H } fn type_of_expr_including_adjust(infer: &InferenceResult, id: ExprId) -> Option<&Ty> { - match infer.expr_adjustments.get(&id).and_then(|adjustments| adjustments.last()) { + match infer.expr_adjustment(id).and_then(|adjustments| adjustments.last()) { Some(adjustment) => Some(&adjustment.target), - None => infer.type_of_expr.get(id), + None => Some(&infer[id]), } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs index b71de5e00c6..c80b78fd970 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs @@ -175,7 +175,7 @@ pub(crate) fn expand_rest_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> // ast::TuplePat(it) => (), // FIXME // ast::SlicePat(it) => (), - _ => return None, + _ => None, } } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs index 6316a8f0db2..603be4d6673 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/promote_local_to_const.rs @@ -3,8 +3,7 @@ use ide_db::{assists::AssistId, defs::Definition}; use stdx::to_upper_snake_case; use syntax::{ AstNode, - ast::{self, HasName, make}, - ted, + ast::{self, HasName, syntax_factory::SyntaxFactory}, }; use crate::{ @@ -69,15 +68,18 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>) "Promote local to constant", let_stmt.syntax().text_range(), |edit| { + let make = SyntaxFactory::with_mappings(); + let mut editor = edit.make_editor(let_stmt.syntax()); let name = to_upper_snake_case(&name.to_string()); let usages = Definition::Local(local).usages(&ctx.sema).all(); if let Some(usages) = usages.references.get(&ctx.file_id()) { - let name_ref = make::name_ref(&name); + let name_ref = make.name_ref(&name); for usage in usages { let Some(usage_name) = usage.name.as_name_ref().cloned() else { continue }; if let Some(record_field) = ast::RecordExprField::for_name_ref(&usage_name) { - let name_expr = make::expr_path(make::path_from_text(&name)); + let path = make.ident_path(&name); + let name_expr = make.expr_path(path); utils::replace_record_field_expr(ctx, edit, record_field, name_expr); } else { let usage_range = usage.range; @@ -86,15 +88,17 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>) } } - let item = make::item_const(None, make::name(&name), make::ty(&ty), initializer) - .clone_for_update(); - let let_stmt = edit.make_mut(let_stmt); + let item = make.item_const(None, make.name(&name), make.ty(&ty), initializer); if let Some((cap, name)) = ctx.config.snippet_cap.zip(item.name()) { - edit.add_tabstop_before(cap, name); + let tabstop = edit.make_tabstop_before(cap); + editor.add_annotation(name.syntax().clone(), tabstop); } - ted::replace(let_stmt.syntax(), item.syntax()); + editor.replace(let_stmt.syntax(), item.syntax()); + + editor.add_mappings(make.finish_with_mappings()); + edit.add_file_edits(ctx.vfs_file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index e933bcc40db..62914ee7f38 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -1,8 +1,5 @@ use ide_db::syntax_helpers::suggest_name; -use syntax::{ - ast::{self, AstNode, make}, - ted, -}; +use syntax::ast::{self, AstNode, syntax_factory::SyntaxFactory}; use crate::{AssistContext, AssistId, Assists}; @@ -60,21 +57,25 @@ pub(crate) fn replace_is_method_with_if_let_method( message, call_expr.syntax().text_range(), |edit| { - let call_expr = edit.make_mut(call_expr); + let make = SyntaxFactory::with_mappings(); + let mut editor = edit.make_editor(call_expr.syntax()); - let var_pat = make::ident_pat(false, false, make::name(&var_name)); - let pat = make::tuple_struct_pat(make::ext::ident_path(text), [var_pat.into()]); - let let_expr = make::expr_let(pat.into(), receiver).clone_for_update(); + let var_pat = make.ident_pat(false, false, make.name(&var_name)); + let pat = make.tuple_struct_pat(make.ident_path(text), [var_pat.into()]); + let let_expr = make.expr_let(pat.into(), receiver); if let Some(cap) = ctx.config.snippet_cap { if let Some(ast::Pat::TupleStructPat(pat)) = let_expr.pat() { if let Some(first_var) = pat.fields().next() { - edit.add_placeholder_snippet(cap, first_var); + let placeholder = edit.make_placeholder_snippet(cap); + editor.add_annotation(first_var.syntax(), placeholder); } } } - ted::replace(call_expr.syntax(), let_expr.syntax()); + editor.replace(call_expr.syntax(), let_expr.syntax()); + editor.add_mappings(make.finish_with_mappings()); + edit.add_file_edits(ctx.vfs_file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs index 109269bd6e6..504e12f93df 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs @@ -1,8 +1,7 @@ use ide_db::assists::AssistId; use syntax::{ AstNode, T, - ast::{self, make}, - ted, + ast::{self, syntax_factory::SyntaxFactory}, }; use crate::{AssistContext, Assists}; @@ -37,8 +36,7 @@ pub(crate) fn toggle_macro_delimiter(acc: &mut Assists, ctx: &AssistContext<'_>) RCur, } - let makro = ctx.find_node_at_offset::<ast::MacroCall>()?.clone_for_update(); - let makro_text_range = makro.syntax().text_range(); + let makro = ctx.find_node_at_offset::<ast::MacroCall>()?; let cursor_offset = ctx.offset(); let semicolon = makro.semicolon_token(); @@ -71,24 +69,28 @@ pub(crate) fn toggle_macro_delimiter(acc: &mut Assists, ctx: &AssistContext<'_>) }, token_tree.syntax().text_range(), |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(makro.syntax()); + match token { MacroDelims::LPar | MacroDelims::RPar => { - ted::replace(ltoken, make::token(T!['{'])); - ted::replace(rtoken, make::token(T!['}'])); + editor.replace(ltoken, make.token(T!['{'])); + editor.replace(rtoken, make.token(T!['}'])); if let Some(sc) = semicolon { - ted::remove(sc); + editor.delete(sc); } } MacroDelims::LBra | MacroDelims::RBra => { - ted::replace(ltoken, make::token(T!['('])); - ted::replace(rtoken, make::token(T![')'])); + editor.replace(ltoken, make.token(T!['('])); + editor.replace(rtoken, make.token(T![')'])); } MacroDelims::LCur | MacroDelims::RCur => { - ted::replace(ltoken, make::token(T!['['])); - ted::replace(rtoken, make::token(T![']'])); + editor.replace(ltoken, make.token(T!['['])); + editor.replace(rtoken, make.token(T![']'])); } } - builder.replace(makro_text_range, makro.syntax().text()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs index 5aedff5cc77..7b0f2dc65a7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -1,8 +1,7 @@ use syntax::{ Direction, SyntaxKind, T, - algo::neighbor, - ast::{self, AstNode, edit::IndentLevel, make}, - ted::{self, Position}, + ast::{self, AstNode, edit::IndentLevel, syntax_factory::SyntaxFactory}, + syntax_editor::{Element, Position}, }; use crate::{AssistContext, AssistId, Assists}; @@ -33,7 +32,7 @@ use crate::{AssistContext, AssistId, Assists}; // ``` pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let pipe_token = ctx.find_token_syntax_at_offset(T![|])?; - let or_pat = ast::OrPat::cast(pipe_token.parent()?)?.clone_for_update(); + let or_pat = ast::OrPat::cast(pipe_token.parent()?)?; if or_pat.leading_pipe().is_some_and(|it| it == pipe_token) { return None; } @@ -44,13 +43,14 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O // without `OrPat`. let new_parent = match_arm.syntax().parent()?; - let old_parent_range = new_parent.text_range(); acc.add( AssistId::refactor_rewrite("unmerge_match_arm"), "Unmerge match arm", pipe_token.text_range(), |edit| { + let make = SyntaxFactory::with_mappings(); + let mut editor = edit.make_editor(&new_parent); let pats_after = pipe_token .siblings_with_tokens(Direction::Next) .filter_map(|it| ast::Pat::cast(it.into_node()?)) @@ -59,11 +59,9 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let new_pat = if pats_after.len() == 1 { pats_after[0].clone() } else { - make::or_pat(pats_after, or_pat.leading_pipe().is_some()).into() + make.or_pat(pats_after, or_pat.leading_pipe().is_some()).into() }; - let new_match_arm = - make::match_arm(new_pat, match_arm.guard(), match_arm_body).clone_for_update(); - + let new_match_arm = make.match_arm(new_pat, match_arm.guard(), match_arm_body); let mut pipe_index = pipe_token.index(); if pipe_token .prev_sibling_or_token() @@ -71,10 +69,13 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O { pipe_index -= 1; } - or_pat.syntax().splice_children( - pipe_index..or_pat.syntax().children_with_tokens().count(), - Vec::new(), - ); + for child in or_pat + .syntax() + .children_with_tokens() + .skip_while(|child| child.index() < pipe_index) + { + editor.delete(child.syntax_element()); + } let mut insert_after_old_arm = Vec::new(); @@ -86,33 +87,19 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O // body is a block, but we don't bother to check that. // - Missing after the arm with arms after, if the arm body is a block. In this case // we don't want to insert a comma at all. - let has_comma_after = - std::iter::successors(match_arm.syntax().last_child_or_token(), |it| { - it.prev_sibling_or_token() - }) - .map(|it| it.kind()) - .find(|it| !it.is_trivia()) - == Some(T![,]); - let has_arms_after = neighbor(&match_arm, Direction::Next).is_some(); - if !has_comma_after && !has_arms_after { - insert_after_old_arm.push(make::token(T![,]).into()); + let has_comma_after = match_arm.comma_token().is_some(); + if !has_comma_after && !match_arm.expr().unwrap().is_block_like() { + insert_after_old_arm.push(make.token(T![,]).into()); } let indent = IndentLevel::from_node(match_arm.syntax()); - insert_after_old_arm.push(make::tokens::whitespace(&format!("\n{indent}")).into()); + insert_after_old_arm.push(make.whitespace(&format!("\n{indent}")).into()); insert_after_old_arm.push(new_match_arm.syntax().clone().into()); - ted::insert_all_raw(Position::after(match_arm.syntax()), insert_after_old_arm); - - if has_comma_after { - ted::insert_raw( - Position::last_child_of(new_match_arm.syntax()), - make::token(T![,]), - ); - } - - edit.replace(old_parent_range, new_parent.to_string()); + editor.insert_all(Position::after(match_arm.syntax()), insert_after_old_arm); + editor.add_mappings(make.finish_with_mappings()); + edit.add_file_edits(ctx.vfs_file_id(), editor); }, ) } @@ -258,7 +245,7 @@ fn main() { let x = X::A; let y = match x { X::A => 1i32, - X::B => 1i32 + X::B => 1i32, }; } "#, @@ -276,7 +263,7 @@ enum X { A, B } fn main() { let x = X::A; match x { - X::A $0| X::B => {}, + X::A $0| X::B => {} } } "#, @@ -287,8 +274,8 @@ enum X { A, B } fn main() { let x = X::A; match x { - X::A => {}, - X::B => {}, + X::A => {} + X::B => {} } } "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index e1b94673e77..5183566d136 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -2,8 +2,7 @@ use ide_db::source_change::SourceChangeBuilder; use itertools::Itertools; use syntax::{ NodeOrToken, SyntaxToken, T, TextRange, algo, - ast::{self, AstNode, make}, - ted::{self, Position}, + ast::{self, AstNode, make, syntax_factory::SyntaxFactory}, }; use crate::{AssistContext, AssistId, Assists}; @@ -173,40 +172,45 @@ fn wrap_derive( } } let handle_source_change = |edit: &mut SourceChangeBuilder| { - let new_derive = make::attr_outer(make::meta_token_tree( - make::ext::ident_path("derive"), - make::token_tree(T!['('], new_derive), - )) - .clone_for_update(); - let meta = make::meta_token_tree( - make::ext::ident_path("cfg_attr"), - make::token_tree( + let make = SyntaxFactory::with_mappings(); + let mut editor = edit.make_editor(attr.syntax()); + let new_derive = make.attr_outer( + make.meta_token_tree(make.ident_path("derive"), make.token_tree(T!['('], new_derive)), + ); + let meta = make.meta_token_tree( + make.ident_path("cfg_attr"), + make.token_tree( T!['('], vec![ - NodeOrToken::Token(make::token(T![,])), - NodeOrToken::Token(make::tokens::whitespace(" ")), - NodeOrToken::Token(make::tokens::ident("derive")), - NodeOrToken::Node(make::token_tree(T!['('], cfg_derive_tokens)), + NodeOrToken::Token(make.token(T![,])), + NodeOrToken::Token(make.whitespace(" ")), + NodeOrToken::Token(make.ident("derive")), + NodeOrToken::Node(make.token_tree(T!['('], cfg_derive_tokens)), ], ), ); - // Remove the derive attribute - let edit_attr = edit.make_syntax_mut(attr.syntax().clone()); - - ted::replace(edit_attr, new_derive.syntax().clone()); - let cfg_attr = make::attr_outer(meta).clone_for_update(); - ted::insert_all_raw( - Position::after(new_derive.syntax().clone()), - vec![make::tokens::whitespace("\n").into(), cfg_attr.syntax().clone().into()], + let cfg_attr = make.attr_outer(meta); + editor.replace_with_many( + attr.syntax(), + vec![ + new_derive.syntax().clone().into(), + make.whitespace("\n").into(), + cfg_attr.syntax().clone().into(), + ], ); + if let Some(snippet_cap) = ctx.config.snippet_cap { if let Some(first_meta) = cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token()) { - edit.add_tabstop_after_token(snippet_cap, first_meta) + let tabstop = edit.make_tabstop_after(snippet_cap); + editor.add_annotation(first_meta, tabstop); } } + + editor.add_mappings(make.finish_with_mappings()); + edit.add_file_edits(ctx.vfs_file_id(), editor); }; acc.add( @@ -221,10 +225,10 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> let range = attr.syntax().text_range(); let path = attr.path()?; let handle_source_change = |edit: &mut SourceChangeBuilder| { - let mut raw_tokens = vec![ - NodeOrToken::Token(make::token(T![,])), - NodeOrToken::Token(make::tokens::whitespace(" ")), - ]; + let make = SyntaxFactory::with_mappings(); + let mut editor = edit.make_editor(attr.syntax()); + let mut raw_tokens = + vec![NodeOrToken::Token(make.token(T![,])), NodeOrToken::Token(make.whitespace(" "))]; path.syntax().descendants_with_tokens().for_each(|it| { if let NodeOrToken::Token(token) = it { raw_tokens.push(NodeOrToken::Token(token)); @@ -232,9 +236,9 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> }); if let Some(meta) = attr.meta() { if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) { - raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" "))); + raw_tokens.push(NodeOrToken::Token(make.whitespace(" "))); raw_tokens.push(NodeOrToken::Token(eq)); - raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" "))); + raw_tokens.push(NodeOrToken::Token(make.whitespace(" "))); expr.syntax().descendants_with_tokens().for_each(|it| { if let NodeOrToken::Token(token) = it { @@ -245,26 +249,24 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> raw_tokens.extend(tt.token_trees_and_tokens()); } } - let meta = make::meta_token_tree( - make::ext::ident_path("cfg_attr"), - make::token_tree(T!['('], raw_tokens), - ); - let cfg_attr = if attr.excl_token().is_some() { - make::attr_inner(meta) - } else { - make::attr_outer(meta) - } - .clone_for_update(); - let attr_syntax = edit.make_syntax_mut(attr.syntax().clone()); - ted::replace(attr_syntax, cfg_attr.syntax()); + let meta = + make.meta_token_tree(make.ident_path("cfg_attr"), make.token_tree(T!['('], raw_tokens)); + let cfg_attr = + if attr.excl_token().is_some() { make.attr_inner(meta) } else { make.attr_outer(meta) }; + + editor.replace(attr.syntax(), cfg_attr.syntax()); if let Some(snippet_cap) = ctx.config.snippet_cap { if let Some(first_meta) = cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token()) { - edit.add_tabstop_after_token(snippet_cap, first_meta) + let tabstop = edit.make_tabstop_after(snippet_cap); + editor.add_annotation(first_meta, tabstop); } } + + editor.add_mappings(make.finish_with_mappings()); + edit.add_file_edits(ctx.vfs_file_id(), editor); }; acc.add( AssistId::refactor("wrap_unwrap_cfg_attr"), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 1a91053f93c..87a4c2ef758 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -1,5 +1,7 @@ //! Assorted functions shared by several assists. +use std::slice; + pub(crate) use gen_trait_fn_body::gen_trait_fn_body; use hir::{ DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, @@ -912,7 +914,7 @@ fn handle_as_ref_str( ) -> Option<(ReferenceConversionType, bool)> { let str_type = hir::BuiltinType::str().ty(db); - ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[str_type.clone()]) + ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&str_type)) .then_some((ReferenceConversionType::AsRefStr, could_deref_to_target(ty, &str_type, db))) } @@ -924,7 +926,7 @@ fn handle_as_ref_slice( let type_argument = ty.type_arguments().next()?; let slice_type = hir::Type::new_slice(type_argument); - ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[slice_type.clone()]).then_some(( + ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&slice_type)).then_some(( ReferenceConversionType::AsRefSlice, could_deref_to_target(ty, &slice_type, db), )) @@ -937,10 +939,11 @@ fn handle_dereferenced( ) -> Option<(ReferenceConversionType, bool)> { let type_argument = ty.type_arguments().next()?; - ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[type_argument.clone()]).then_some(( - ReferenceConversionType::Dereferenced, - could_deref_to_target(ty, &type_argument, db), - )) + ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&type_argument)) + .then_some(( + ReferenceConversionType::Dereferenced, + could_deref_to_target(ty, &type_argument, db), + )) } fn handle_option_as_ref( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs index 411902f1117..46a36300459 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs @@ -878,6 +878,7 @@ mod derive { expect![[r#" de Clone macro Clone de Clone, Copy + de Debug macro Debug de Default macro Default de PartialEq macro PartialEq de PartialEq, Eq @@ -900,6 +901,7 @@ mod derive { expect![[r#" de Clone macro Clone de Clone, Copy + de Debug macro Debug de Default macro Default de Eq de Eq, PartialOrd, Ord @@ -921,6 +923,7 @@ mod derive { expect![[r#" de Clone macro Clone de Clone, Copy + de Debug macro Debug de Default macro Default de Eq de Eq, PartialOrd, Ord @@ -942,6 +945,7 @@ mod derive { expect![[r#" de Clone macro Clone de Clone, Copy + de Debug macro Debug de Default macro Default de PartialOrd de PartialOrd, Ord diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index 994150b1ac4..8e687385086 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -106,6 +106,18 @@ impl FamousDefs<'_, '_> { self.find_trait("core:convert:AsRef") } + pub fn core_convert_AsMut(&self) -> Option<Trait> { + self.find_trait("core:convert:AsMut") + } + + pub fn core_borrow_Borrow(&self) -> Option<Trait> { + self.find_trait("core:borrow:Borrow") + } + + pub fn core_borrow_BorrowMut(&self) -> Option<Trait> { + self.find_trait("core:borrow:BorrowMut") + } + pub fn core_ops_ControlFlow(&self) -> Option<Enum> { self.find_enum("core:ops:ControlFlow") } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs index 5356614dce5..e6618573e09 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs @@ -272,5 +272,5 @@ fn crate_name(db: &RootDatabase, krate: Crate) -> Symbol { .display_name .as_deref() .cloned() - .unwrap_or_else(|| Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize)) + .unwrap_or_else(|| Symbol::integer(salsa::plumbing::AsId::as_id(&krate).index() as usize)) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 7d460f72492..4efb83ba323 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -317,7 +317,7 @@ impl Definition { }; return match def { Some(def) => SearchScope::file_range( - def.as_ref().original_file_range_with_macro_call_body(db), + def.as_ref().original_file_range_with_macro_call_input(db), ), None => SearchScope::single_file(file_id), }; @@ -332,7 +332,7 @@ impl Definition { }; return match def { Some(def) => SearchScope::file_range( - def.as_ref().original_file_range_with_macro_call_body(db), + def.as_ref().original_file_range_with_macro_call_input(db), ), None => SearchScope::single_file(file_id), }; @@ -341,7 +341,7 @@ impl Definition { if let Definition::SelfType(impl_) = self { return match impl_.source(db).map(|src| src.syntax().cloned()) { Some(def) => SearchScope::file_range( - def.as_ref().original_file_range_with_macro_call_body(db), + def.as_ref().original_file_range_with_macro_call_input(db), ), None => SearchScope::single_file(file_id), }; @@ -360,7 +360,7 @@ impl Definition { }; return match def { Some(def) => SearchScope::file_range( - def.as_ref().original_file_range_with_macro_call_body(db), + def.as_ref().original_file_range_with_macro_call_input(db), ), None => SearchScope::single_file(file_id), }; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs index 546512a6cf9..c39e00e178f 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs @@ -242,8 +242,8 @@ macro_rules! outer { fn f() { outer!(); -} //^^^^^^^^ error: leftover tokens - //^^^^^^^^ error: Syntax Error in Expansion: expected expression +} //^^^^^^ error: leftover tokens + //^^^^^^ error: Syntax Error in Expansion: expected expression "#, ) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 8a5d82b48c0..7da799e0d49 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -66,7 +66,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass let current_module = ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module()); let range = InFile::new(d.file, d.field_list_parent.text_range()) - .original_node_file_range_rooted(ctx.sema.db); + .original_node_file_range_rooted_opt(ctx.sema.db)?; let build_text_edit = |new_syntax: &SyntaxNode, old_syntax| { let edit = { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 0928262d22f..1e80d02926d 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -239,4 +239,22 @@ impl S { "#, ) } + + #[test] + fn regression_20155() { + check_diagnostics( + r#" +//- minicore: copy, option +struct Box(i32); +fn test() { + let b = Some(Box(0)); + || { + if let Some(b) = b { + let _move = b; + } + }; +} +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs index 4327b12dce7..fc2648efb40 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs @@ -77,6 +77,7 @@ fn quickfix_for_redundant_assoc_item( redundant_item_def: String, range: TextRange, ) -> Option<Vec<Assist>> { + let file_id = d.file_id.file_id()?; let add_assoc_item_def = |builder: &mut SourceChangeBuilder| -> Option<()> { let db = ctx.sema.db; let root = db.parse_or_expand(d.file_id); @@ -90,12 +91,14 @@ fn quickfix_for_redundant_assoc_item( let trait_def = d.trait_.source(db)?.value; let l_curly = trait_def.assoc_item_list()?.l_curly_token()?.text_range(); let where_to_insert = - hir::InFile::new(d.file_id, l_curly).original_node_file_range_rooted(db).range; + hir::InFile::new(d.file_id, l_curly).original_node_file_range_rooted_opt(db)?; + if where_to_insert.file_id != file_id { + return None; + } - builder.insert(where_to_insert.end(), redundant_item_def); + builder.insert(where_to_insert.range.end(), redundant_item_def); Some(()) }; - let file_id = d.file_id.file_id()?; let mut source_change_builder = SourceChangeBuilder::new(file_id.file_id(ctx.sema.db)); add_assoc_item_def(&mut source_change_builder)?; diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 1f2d671249d..dcca85d4db3 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -120,8 +120,7 @@ fn assoc_func_fix( let call = ast::MethodCallExpr::cast(expr.syntax().clone())?; let range = InFile::new(expr_ptr.file_id, call.syntax().text_range()) - .original_node_file_range_rooted(db) - .range; + .original_node_file_range_rooted_opt(db)?; let receiver = call.receiver()?; let receiver_type = &ctx.sema.type_of_expr(&receiver)?.original; @@ -174,18 +173,16 @@ fn assoc_func_fix( let assoc_func_call_expr_string = make::expr_call(assoc_func_path, args).to_string(); - let file_id = ctx.sema.original_range_opt(call.receiver()?.syntax())?.file_id; - Some(Assist { id: AssistId::quick_fix("method_call_to_assoc_func_call_fix"), label: Label::new(format!( "Use associated func call instead: `{assoc_func_call_expr_string}`" )), group: None, - target: range, + target: range.range, source_change: Some(SourceChange::from_text_edit( - file_id.file_id(ctx.sema.db), - TextEdit::replace(range, assoc_func_call_expr_string), + range.file_id.file_id(ctx.sema.db), + TextEdit::replace(range.range, assoc_func_call_expr_string), )), command: None, }) @@ -300,7 +297,7 @@ macro_rules! m { } fn main() { m!(()); - // ^^^^^^ error: no method `foo` on type `()` + // ^^ error: no method `foo` on type `()` } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs index 4b8d07a2533..7a0405939d1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs +++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs @@ -592,7 +592,7 @@ macro_rules! call { "#, expect!["callee Function FileId(0) 22..37 30..36"], expect![[r#" - caller Function FileId(0) 38..52 : FileId(0):44..50 + caller Function FileId(0) 38..43 : FileId(0):44..50 caller Function FileId(1) 130..136 130..136 : FileId(0):44..50 callee Function FileId(0) 38..52 44..50 : FileId(0):44..50"#]], expect![[]], diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 2c983287d89..f58202a4213 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -60,7 +60,7 @@ pub(crate) fn rewrite_links( let doc = Parser::new_with_broken_link_callback(markdown, MARKDOWN_OPTIONS, Some(&mut cb)) .into_offset_iter(); - let doc = map_links(doc, |target, title, range| { + let doc = map_links(doc, |target, title, range, link_type| { // This check is imperfect, there's some overlap between valid intra-doc links // and valid URLs so we choose to be too eager to try to resolve what might be // a URL. @@ -78,7 +78,7 @@ pub(crate) fn rewrite_links( .map(|(_, attr_id)| attr_id.is_inner_attr()) .unwrap_or(false); if let Some((target, title)) = - rewrite_intra_doc_link(db, definition, target, title, is_inner_doc) + rewrite_intra_doc_link(db, definition, target, title, is_inner_doc, link_type) { (None, target, title) } else if let Some(target) = rewrite_url_link(db, definition, target) { @@ -417,6 +417,7 @@ fn rewrite_intra_doc_link( target: &str, title: &str, is_inner_doc: bool, + link_type: LinkType, ) -> Option<(String, String)> { let (link, ns) = parse_intra_doc_link(target); @@ -438,7 +439,21 @@ fn rewrite_intra_doc_link( url = url.join(&file).ok()?; url.set_fragment(frag); - Some((url.into(), strip_prefixes_suffixes(title).to_owned())) + // We want to strip the keyword prefix from the title, but only if the target is implicitly the same + // as the title. + let title = match link_type { + LinkType::Email + | LinkType::Autolink + | LinkType::Shortcut + | LinkType::Collapsed + | LinkType::Reference + | LinkType::Inline => title.to_owned(), + LinkType::ShortcutUnknown | LinkType::CollapsedUnknown | LinkType::ReferenceUnknown => { + strip_prefixes_suffixes(title).to_owned() + } + }; + + Some((url.into(), title)) } /// Try to resolve path to local documentation via path-based links (i.e. `../gateway/struct.Shard.html`). @@ -470,7 +485,7 @@ fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> { /// Rewrites a markdown document, applying 'callback' to each link. fn map_links<'e>( events: impl Iterator<Item = (Event<'e>, Range<usize>)>, - callback: impl Fn(&str, &str, Range<usize>) -> (Option<LinkType>, String, String), + callback: impl Fn(&str, &str, Range<usize>, LinkType) -> (Option<LinkType>, String, String), ) -> impl Iterator<Item = Event<'e>> { let mut in_link = false; // holds the origin link target on start event and the rewritten one on end event @@ -497,7 +512,7 @@ fn map_links<'e>( } Event::Text(s) if in_link => { let (link_type, link_target_s, link_name) = - callback(&end_link_target.take().unwrap(), &s, range); + callback(&end_link_target.take().unwrap(), &s, range, end_link_type.unwrap()); end_link_target = Some(CowStr::Boxed(link_target_s.into())); if !matches!(end_link_type, Some(LinkType::Autolink)) { end_link_type = link_type; @@ -506,7 +521,7 @@ fn map_links<'e>( } Event::Code(s) if in_link => { let (link_type, link_target_s, link_name) = - callback(&end_link_target.take().unwrap(), &s, range); + callback(&end_link_target.take().unwrap(), &s, range, end_link_type.unwrap()); end_link_target = Some(CowStr::Boxed(link_target_s.into())); if !matches!(end_link_type, Some(LinkType::Autolink)) { end_link_type = link_type; diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs index 347da4e85b4..6820f99facf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs +++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs @@ -329,7 +329,7 @@ macro_rules! mcexp { #[deprecated] fn obsolete() {} -#[deprecated(note = "for awhile")] +#[deprecated(note = "for a while")] fn very_obsolete() {} // region: Some region name @@ -608,8 +608,8 @@ fn let_statements() { StructureNode { parent: None, label: "very_obsolete", - navigation_range: 511..524, - node_range: 473..529, + navigation_range: 512..525, + node_range: 473..530, kind: SymbolKind( Function, ), @@ -621,8 +621,8 @@ fn let_statements() { StructureNode { parent: None, label: "Some region name", - navigation_range: 531..558, - node_range: 531..558, + navigation_range: 532..559, + node_range: 532..559, kind: Region, detail: None, deprecated: false, @@ -630,8 +630,8 @@ fn let_statements() { StructureNode { parent: None, label: "m", - navigation_range: 598..599, - node_range: 573..636, + navigation_range: 599..600, + node_range: 574..637, kind: SymbolKind( Module, ), @@ -643,8 +643,8 @@ fn let_statements() { 22, ), label: "dontpanic", - navigation_range: 573..593, - node_range: 573..593, + navigation_range: 574..594, + node_range: 574..594, kind: Region, detail: None, deprecated: false, @@ -654,8 +654,8 @@ fn let_statements() { 22, ), label: "f", - navigation_range: 605..606, - node_range: 602..611, + navigation_range: 606..607, + node_range: 603..612, kind: SymbolKind( Function, ), @@ -669,8 +669,8 @@ fn let_statements() { 22, ), label: "g", - navigation_range: 628..629, - node_range: 612..634, + navigation_range: 629..630, + node_range: 613..635, kind: SymbolKind( Function, ), @@ -682,8 +682,8 @@ fn let_statements() { StructureNode { parent: None, label: "extern \"C\"", - navigation_range: 638..648, - node_range: 638..651, + navigation_range: 639..649, + node_range: 639..652, kind: ExternBlock, detail: None, deprecated: false, @@ -691,8 +691,8 @@ fn let_statements() { StructureNode { parent: None, label: "let_statements", - navigation_range: 656..670, - node_range: 653..813, + navigation_range: 657..671, + node_range: 654..814, kind: SymbolKind( Function, ), @@ -706,8 +706,8 @@ fn let_statements() { 27, ), label: "x", - navigation_range: 683..684, - node_range: 679..690, + navigation_range: 684..685, + node_range: 680..691, kind: SymbolKind( Local, ), @@ -719,8 +719,8 @@ fn let_statements() { 27, ), label: "mut y", - navigation_range: 699..704, - node_range: 695..709, + navigation_range: 700..705, + node_range: 696..710, kind: SymbolKind( Local, ), @@ -732,8 +732,8 @@ fn let_statements() { 27, ), label: "Foo { .. }", - navigation_range: 718..740, - node_range: 714..753, + navigation_range: 719..741, + node_range: 715..754, kind: SymbolKind( Local, ), @@ -745,8 +745,8 @@ fn let_statements() { 27, ), label: "_", - navigation_range: 803..804, - node_range: 799..811, + navigation_range: 804..805, + node_range: 800..812, kind: SymbolKind( Local, ), diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index fd465f31d43..29fc68bb50f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -1082,7 +1082,7 @@ macro_rules! define_fn { } define_fn!(); -//^^^^^^^^^^^^^ +//^^^^^^^^^^ fn bar() { $0foo(); } @@ -3228,7 +3228,7 @@ mod bar { use crate::m; m!(); - // ^^^^^ + // ^^ fn qux() { Foo$0; @@ -3851,4 +3851,76 @@ fn main() { "#, ); } + + #[test] + fn goto_const_from_match_pat_with_tuple_struct() { + check( + r#" +struct Tag(u8); +struct Path {} + +const Path: u8 = 0; + // ^^^^ +fn main() { + match Tag(Path) { + Tag(Path$0) => {} + _ => {} + } +} + +"#, + ); + } + + #[test] + fn goto_const_from_match_pat() { + check( + r#" +type T1 = u8; +const T1: u8 = 0; + // ^^ +fn main() { + let x = 0; + match x { + T1$0 => {} + _ => {} + } +} +"#, + ); + } + + #[test] + fn goto_struct_from_match_pat() { + check( + r#" +struct T1; + // ^^ +fn main() { + let x = 0; + match x { + T1$0 => {} + _ => {} + } +} +"#, + ); + } + + #[test] + fn no_goto_trait_from_match_pat() { + check( + r#" +trait T1 {} +fn main() { + let x = 0; + match x { + T1$0 => {} + // ^^ + _ => {} + } +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index a281a491525..f63499aa0fd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -10927,3 +10927,34 @@ fn main() { "#]], ); } + +#[test] +fn keyword_inside_link() { + check( + r#" +enum Foo { + MacroExpansion, +} + +/// I return a [macro expansion](Foo::MacroExpansion). +fn bar$0() -> Foo { + Foo::MacroExpansion +} + "#, + expect. + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index f2844a2eaa6..49b43fc37f2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -109,50 +109,90 @@ pub(super) fn hints( } has_adjustments = true; - // FIXME: Add some nicer tooltips to each of these - let (text, coercion) = match kind { + let (text, coercion, detailed_tooltip) = match kind { Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => { allow_edit = false; - ("<never-to-any>", "never to any") - } - Adjust::Deref(None) => ("*", "dereference"), - Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => { - ("*", "`Deref` dereference") - } - Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => { - ("*", "`DerefMut` dereference") - } - Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => ("&", "borrow"), - Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => ("&mut ", "unique borrow"), - Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => { - ("&raw const ", "const pointer borrow") - } - Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => { - ("&raw mut ", "mut pointer borrow") + ( + "<never-to-any>", + "never to any", + "Coerces the never type `!` into any other type. This happens in code paths that never return, like after `panic!()` or `return`.", + ) } + Adjust::Deref(None) => ( + "*", + "dereference", + "Built-in dereference of a reference to access the underlying value. The compiler inserts `*` to get the value from `&T`.", + ), + Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => ( + "*", + "`Deref` dereference", + "Dereference via the `Deref` trait. Used for types like `Box<T>` or `Rc<T>` so they act like plain `T`.", + ), + Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => ( + "*", + "`DerefMut` dereference", + "Mutable dereference using the `DerefMut` trait. Enables smart pointers to give mutable access to their inner values.", + ), + Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => ( + "&", + "shared borrow", + "Inserts `&` to create a shared reference. Lets you use a value without moving or cloning it.", + ), + Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => ( + "&mut ", + "mutable borrow", + "Inserts `&mut` to create a unique, mutable reference. Lets you modify a value without taking ownership.", + ), + Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => ( + "&raw const ", + "const raw pointer", + "Converts a reference to a raw const pointer `*const T`. Often used when working with FFI or unsafe code.", + ), + Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => ( + "&raw mut ", + "mut raw pointer", + "Converts a mutable reference to a raw mutable pointer `*mut T`. Allows mutation in unsafe contexts.", + ), // some of these could be represented via `as` casts, but that's not too nice and // handling everything as a prefix expr makes the `(` and `)` insertion easier Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => { allow_edit = false; match cast { - PointerCast::ReifyFnPointer => { - ("<fn-item-to-fn-pointer>", "fn item to fn pointer") - } + PointerCast::ReifyFnPointer => ( + "<fn-item-to-fn-pointer>", + "fn item to fn pointer", + "Converts a named function to a function pointer `fn()`. Useful when passing functions as values.", + ), PointerCast::UnsafeFnPointer => ( "<safe-fn-pointer-to-unsafe-fn-pointer>", "safe fn pointer to unsafe fn pointer", + "Coerces a safe function pointer to an unsafe one. Allows calling it in an unsafe context.", + ), + PointerCast::ClosureFnPointer(Safety::Unsafe) => ( + "<closure-to-unsafe-fn-pointer>", + "closure to unsafe fn pointer", + "Converts a non-capturing closure to an unsafe function pointer. Required for use in `extern` or unsafe APIs.", + ), + PointerCast::ClosureFnPointer(Safety::Safe) => ( + "<closure-to-fn-pointer>", + "closure to fn pointer", + "Converts a non-capturing closure to a function pointer. Lets closures behave like plain functions.", + ), + PointerCast::MutToConstPointer => ( + "<mut-ptr-to-const-ptr>", + "mut ptr to const ptr", + "Coerces `*mut T` to `*const T`. Safe because const pointers restrict what you can do.", + ), + PointerCast::ArrayToPointer => ( + "<array-ptr-to-element-ptr>", + "array to pointer", + "Converts an array to a pointer to its first element. Similar to how arrays decay to pointers in C.", + ), + PointerCast::Unsize => ( + "<unsize>", + "unsize coercion", + "Converts a sized type to an unsized one. Used for things like turning arrays into slices or concrete types into trait objects.", ), - PointerCast::ClosureFnPointer(Safety::Unsafe) => { - ("<closure-to-unsafe-fn-pointer>", "closure to unsafe fn pointer") - } - PointerCast::ClosureFnPointer(Safety::Safe) => { - ("<closure-to-fn-pointer>", "closure to fn pointer") - } - PointerCast::MutToConstPointer => { - ("<mut-ptr-to-const-ptr>", "mut ptr to const ptr") - } - PointerCast::ArrayToPointer => ("<array-ptr-to-element-ptr>", ""), - PointerCast::Unsize => ("<unsize>", "unsize"), } } _ => continue, @@ -162,9 +202,11 @@ pub(super) fn hints( linked_location: None, tooltip: Some(config.lazy_tooltip(|| { InlayTooltip::Markdown(format!( - "`{}` → `{}` ({coercion} coercion)", + "`{}` → `{}`\n\n**{}**\n\n{}", source.display(sema.db, display_target), target.display(sema.db, display_target), + coercion, + detailed_tooltip )) })), }; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs index d2216e66ccb..05253b67948 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs @@ -91,8 +91,6 @@ pub(super) fn hints( match_ast! { match parent { ast::Fn(it) => { - // FIXME: this could include parameters, but `HirDisplay` prints too much info - // and doesn't respect the max length either, so the hints end up way too long (format!("fn {}", it.name()?), it.name().map(name)) }, ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)), diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index 4c7c597e684..7dc18141bdb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -844,7 +844,7 @@ pub(crate) fn orig_range_with_focus_r( // *should* contain the name _ => { let kind = call_kind(); - let range = kind.clone().original_call_range_with_body(db); + let range = kind.clone().original_call_range_with_input(db); //If the focus range is in the attribute/derive body, we // need to point the call site to the entire body, if not, fall back // to the name range of the attribute/derive call diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index f48150b369f..9d1a5bae96f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -351,7 +351,7 @@ pub(crate) fn runnable_fn( ) .call_site(); - let file_range = fn_source.syntax().original_file_range_with_macro_call_body(sema.db); + let file_range = fn_source.syntax().original_file_range_with_macro_call_input(sema.db); let update_test = UpdateTest::find_snapshot_macro(sema, &fn_source.file_syntax(sema.db), file_range); @@ -425,7 +425,7 @@ pub(crate) fn runnable_impl( let impl_source = sema.source(*def)?; let impl_syntax = impl_source.syntax(); - let file_range = impl_syntax.original_file_range_with_macro_call_body(sema.db); + let file_range = impl_syntax.original_file_range_with_macro_call_input(sema.db); let update_test = UpdateTest::find_snapshot_macro(sema, &impl_syntax.file_syntax(sema.db), file_range); @@ -1241,10 +1241,10 @@ generate_main!(); [ "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 0..345, name: \"\", kind: Module })", "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 282..312, focus_range: 286..291, name: \"tests\", kind: Module, description: \"mod tests\" })", - "(Test, NavigationTarget { file_id: FileId(0), full_range: 298..310, name: \"foo_test\", kind: Function })", - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 313..326, name: \"tests2\", kind: Module, description: \"mod tests2\" }, true)", - "(Test, NavigationTarget { file_id: FileId(0), full_range: 313..326, name: \"foo_test2\", kind: Function }, true)", - "(Bin, NavigationTarget { file_id: FileId(0), full_range: 327..344, name: \"main\", kind: Function })", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 298..307, name: \"foo_test\", kind: Function })", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 313..323, name: \"tests2\", kind: Module, description: \"mod tests2\" }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 313..323, name: \"foo_test2\", kind: Function }, true)", + "(Bin, NavigationTarget { file_id: FileId(0), full_range: 327..341, name: \"main\", kind: Function })", ] "#]], ); @@ -1272,10 +1272,10 @@ foo!(); "#, expect![[r#" [ - "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo_tests\", kind: Module, description: \"mod foo_tests\" }, true)", - "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo0\", kind: Function }, true)", - "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo1\", kind: Function }, true)", - "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..217, name: \"foo2\", kind: Function }, true)", + "(TestMod, NavigationTarget { file_id: FileId(0), full_range: 210..214, name: \"foo_tests\", kind: Module, description: \"mod foo_tests\" }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..214, name: \"foo0\", kind: Function }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..214, name: \"foo1\", kind: Function }, true)", + "(Test, NavigationTarget { file_id: FileId(0), full_range: 210..214, name: \"foo2\", kind: Function }, true)", ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs index 7985279679c..25deffe10eb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs @@ -79,7 +79,7 @@ impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> { } fn node_id(&'a self, n: &Crate) -> Id<'a> { - let id = n.as_id().as_u32(); + let id = n.as_id().index(); Id::new(format!("_{id:?}")).unwrap() } diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 52f59679b58..26ee698af08 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -11,7 +11,7 @@ use hir_expand::proc_macro::{ }; use ide_db::{ ChangeWithProcMacros, FxHashMap, RootDatabase, - base_db::{CrateGraphBuilder, Env, SourceRoot, SourceRootId}, + base_db::{CrateGraphBuilder, Env, ProcMacroLoadingError, SourceRoot, SourceRootId}, prime_caches, }; use itertools::Itertools; @@ -69,6 +69,23 @@ pub fn load_workspace( extra_env: &FxHashMap<String, Option<String>>, load_config: &LoadCargoConfig, ) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> { + let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<u16>().ok()); + let mut db = RootDatabase::new(lru_cap); + + let (vfs, proc_macro_server) = load_workspace_into_db(ws, extra_env, load_config, &mut db)?; + + Ok((db, vfs, proc_macro_server)) +} + +// This variant of `load_workspace` allows deferring the loading of rust-analyzer +// into an existing database, which is useful in certain third-party scenarios, +// now that `salsa` supports extending foreign databases (e.g. `RootDatabase`). +pub fn load_workspace_into_db( + ws: ProjectWorkspace, + extra_env: &FxHashMap<String, Option<String>>, + load_config: &LoadCargoConfig, + db: &mut RootDatabase, +) -> anyhow::Result<(vfs::Vfs, Option<ProcMacroClient>)> { let (sender, receiver) = unbounded(); let mut vfs = vfs::Vfs::default(); let mut loader = { @@ -78,23 +95,27 @@ pub fn load_workspace( tracing::debug!(?load_config, "LoadCargoConfig"); let proc_macro_server = match &load_config.with_proc_macro_server { - ProcMacroServerChoice::Sysroot => ws - .find_sysroot_proc_macro_srv() - .and_then(|it| ProcMacroClient::spawn(&it, extra_env).map_err(Into::into)) - .map_err(|e| (e, true)), + ProcMacroServerChoice::Sysroot => ws.find_sysroot_proc_macro_srv().map(|it| { + it.and_then(|it| ProcMacroClient::spawn(&it, extra_env).map_err(Into::into)).map_err( + |e| ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str()), + ) + }), ProcMacroServerChoice::Explicit(path) => { - ProcMacroClient::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true)) - } - ProcMacroServerChoice::None => { - Err((anyhow::format_err!("proc macro server disabled"), false)) + Some(ProcMacroClient::spawn(path, extra_env).map_err(|e| { + ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str()) + })) } + ProcMacroServerChoice::None => Some(Err(ProcMacroLoadingError::Disabled)), }; match &proc_macro_server { - Ok(server) => { - tracing::info!(path=%server.server_path(), "Proc-macro server started") + Some(Ok(server)) => { + tracing::info!(manifest=%ws.manifest_or_root(), path=%server.server_path(), "Proc-macro server started") } - Err((e, _)) => { - tracing::info!(%e, "Failed to start proc-macro server") + Some(Err(e)) => { + tracing::info!(manifest=%ws.manifest_or_root(), %e, "Failed to start proc-macro server") + } + None => { + tracing::info!(manifest=%ws.manifest_or_root(), "No proc-macro server started") } } @@ -111,22 +132,24 @@ pub fn load_workspace( ); let proc_macros = { let proc_macro_server = match &proc_macro_server { - Ok(it) => Ok(it), - Err((e, hard_err)) => Err((e.to_string(), *hard_err)), + Some(Ok(it)) => Ok(it), + Some(Err(e)) => { + Err(ProcMacroLoadingError::ProcMacroSrvError(e.to_string().into_boxed_str())) + } + None => Err(ProcMacroLoadingError::ProcMacroSrvError( + "proc-macro-srv is not running, workspace is missing a sysroot".into(), + )), }; proc_macros .into_iter() .map(|(crate_id, path)| { ( crate_id, - path.map_or_else( - |e| Err((e, true)), - |(_, path)| { - proc_macro_server.as_ref().map_err(Clone::clone).and_then( - |proc_macro_server| load_proc_macro(proc_macro_server, &path, &[]), - ) - }, - ), + path.map_or_else(Err, |(_, path)| { + proc_macro_server.as_ref().map_err(Clone::clone).and_then( + |proc_macro_server| load_proc_macro(proc_macro_server, &path, &[]), + ) + }), ) }) .collect() @@ -139,18 +162,20 @@ pub fn load_workspace( version: 0, }); - let db = load_crate_graph( + load_crate_graph_into_db( crate_graph, proc_macros, project_folders.source_root_config, &mut vfs, &receiver, + db, ); if load_config.prefill_caches { - prime_caches::parallel_prime_caches(&db, 1, &|_| ()); + prime_caches::parallel_prime_caches(db, 1, &|_| ()); } - Ok((db, vfs, proc_macro_server.ok())) + + Ok((vfs, proc_macro_server.and_then(Result::ok))) } #[derive(Default)] @@ -391,11 +416,13 @@ pub fn load_proc_macro( path: &AbsPath, ignored_macros: &[Box<str>], ) -> ProcMacroLoadResult { - let res: Result<Vec<_>, String> = (|| { + let res: Result<Vec<_>, _> = (|| { let dylib = MacroDylib::new(path.to_path_buf()); - let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?; + let vec = server.load_dylib(dylib).map_err(|e| { + ProcMacroLoadingError::ProcMacroSrvError(format!("{e}").into_boxed_str()) + })?; if vec.is_empty() { - return Err("proc macro library returned no proc macros".to_owned()); + return Err(ProcMacroLoadingError::NoProcMacros); } Ok(vec .into_iter() @@ -412,20 +439,19 @@ pub fn load_proc_macro( } Err(e) => { tracing::warn!("proc-macro loading for {path} failed: {e}"); - Err((e, true)) + Err(e) } } } -fn load_crate_graph( +fn load_crate_graph_into_db( crate_graph: CrateGraphBuilder, proc_macros: ProcMacrosBuilder, source_root_config: SourceRootConfig, vfs: &mut vfs::Vfs, receiver: &Receiver<vfs::loader::Message>, -) -> RootDatabase { - let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<u16>().ok()); - let mut db = RootDatabase::new(lru_cap); + db: &mut RootDatabase, +) { let mut analysis_change = ChangeWithProcMacros::default(); db.enable_proc_attr_macros(); @@ -462,7 +488,6 @@ fn load_crate_graph( analysis_change.set_proc_macros(proc_macros); db.apply_change(analysis_change); - db } fn expander_to_proc_macro( diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs index bbaa8f4f292..499caa622c4 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs @@ -312,7 +312,9 @@ impl WorkspaceBuildScripts { match message { Message::BuildScriptExecuted(mut message) => { with_output_for(&message.package_id.repr, &mut |name, data| { - progress(format!("running build-script: {name}")); + progress(format!( + "building compile-time-deps: build script {name} run" + )); let cfgs = { let mut acc = Vec::new(); for cfg in &message.cfgs { @@ -343,7 +345,9 @@ impl WorkspaceBuildScripts { } Message::CompilerArtifact(message) => { with_output_for(&message.package_id.repr, &mut |name, data| { - progress(format!("building proc-macros: {name}")); + progress(format!( + "building compile-time-deps: proc-macro {name} built" + )); if message.target.kind.contains(&cargo_metadata::TargetKind::ProcMacro) { // Skip rmeta file @@ -409,13 +413,6 @@ impl WorkspaceBuildScripts { cmd.arg("--target-dir").arg(target_dir); } - // --all-targets includes tests, benches and examples in addition to the - // default lib and bins. This is an independent concept from the --target - // flag below. - if config.all_targets { - cmd.arg("--all-targets"); - } - if let Some(target) = &config.target { cmd.args(["--target", target]); } @@ -463,14 +460,26 @@ impl WorkspaceBuildScripts { cmd.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly"); cmd.arg("-Zunstable-options"); cmd.arg("--compile-time-deps"); - } else if config.wrap_rustc_in_build_scripts { - // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use - // that to compile only proc macros and build scripts during the initial - // `cargo check`. - // We don't need this if we are using `--compile-time-deps` flag. - let myself = std::env::current_exe()?; - cmd.env("RUSTC_WRAPPER", myself); - cmd.env("RA_RUSTC_WRAPPER", "1"); + // we can pass this unconditionally, because we won't actually build the + // binaries, and as such, this will succeed even on targets without libtest + cmd.arg("--all-targets"); + } else { + // --all-targets includes tests, benches and examples in addition to the + // default lib and bins. This is an independent concept from the --target + // flag below. + if config.all_targets { + cmd.arg("--all-targets"); + } + + if config.wrap_rustc_in_build_scripts { + // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use + // that to compile only proc macros and build scripts during the initial + // `cargo check`. + // We don't need this if we are using `--compile-time-deps` flag. + let myself = std::env::current_exe()?; + cmd.env("RUSTC_WRAPPER", myself); + cmd.env("RA_RUSTC_WRAPPER", "1"); + } } Ok(cmd) } diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 4b34fc00711..9f19260d309 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -163,18 +163,18 @@ impl Sysroot { } } - pub fn discover_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> { - let Some(root) = self.root() else { - return Err(anyhow::format_err!("no sysroot",)); - }; - ["libexec", "lib"] - .into_iter() - .map(|segment| root.join(segment).join("rust-analyzer-proc-macro-srv")) - .find_map(|server_path| probe_for_binary(server_path.into())) - .map(AbsPathBuf::assert) - .ok_or_else(|| { - anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", root) - }) + pub fn discover_proc_macro_srv(&self) -> Option<anyhow::Result<AbsPathBuf>> { + let root = self.root()?; + Some( + ["libexec", "lib"] + .into_iter() + .map(|segment| root.join(segment).join("rust-analyzer-proc-macro-srv")) + .find_map(|server_path| probe_for_binary(server_path.into())) + .map(AbsPathBuf::assert) + .ok_or_else(|| { + anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", root) + }), + ) } fn assemble( @@ -209,6 +209,7 @@ impl Sysroot { pub fn load_workspace( &self, sysroot_source_config: &RustSourceWorkspaceConfig, + no_deps: bool, current_dir: &AbsPath, progress: &dyn Fn(String), ) -> Option<RustLibSrcWorkspace> { @@ -224,6 +225,7 @@ impl Sysroot { &library_manifest, current_dir, cargo_config, + no_deps, progress, ) { Ok(loaded) => return Some(loaded), @@ -318,6 +320,7 @@ impl Sysroot { library_manifest: &ManifestPath, current_dir: &AbsPath, cargo_config: &CargoMetadataConfig, + no_deps: bool, progress: &dyn Fn(String), ) -> Result<RustLibSrcWorkspace> { tracing::debug!("Loading library metadata: {library_manifest}"); @@ -333,7 +336,7 @@ impl Sysroot { current_dir, &cargo_config, self, - false, + no_deps, // Make sure we never attempt to write to the sysroot true, progress, diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 4f11af2d06c..f229e9a650d 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -240,7 +240,7 @@ fn smoke_test_real_sysroot_cargo() { let cwd = AbsPathBuf::assert_utf8(temp_dir().join("smoke_test_real_sysroot_cargo")); std::fs::create_dir_all(&cwd).unwrap(); let loaded_sysroot = - sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &cwd, &|_| ()); + sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), false, &cwd, &|_| ()); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 5bc64df535c..43db84b4fa3 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -7,8 +7,8 @@ use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread}; use anyhow::Context; use base_db::{ CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, - CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroPaths, - TargetLayoutLoadResult, + CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroLoadingError, + ProcMacroPaths, TargetLayoutLoadResult, }; use cfg::{CfgAtom, CfgDiff, CfgOptions}; use intern::{Symbol, sym}; @@ -391,6 +391,7 @@ impl ProjectWorkspace { toolchain.clone(), target_dir.clone(), )), + config.no_deps, workspace_dir, progress, ) @@ -499,6 +500,7 @@ impl ProjectWorkspace { if let Some(sysroot_project) = sysroot_project { sysroot.load_workspace( &RustSourceWorkspaceConfig::Json(*sysroot_project), + config.no_deps, project_root, progress, ) @@ -510,6 +512,7 @@ impl ProjectWorkspace { toolchain.clone(), target_dir, )), + config.no_deps, project_root, progress, ) @@ -570,6 +573,7 @@ impl ProjectWorkspace { toolchain.clone(), target_dir.clone(), )), + config.no_deps, dir, &|_| (), ); @@ -744,7 +748,7 @@ impl ProjectWorkspace { } } - pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> { + pub fn find_sysroot_proc_macro_srv(&self) -> Option<anyhow::Result<AbsPathBuf>> { self.sysroot.discover_proc_macro_srv() } @@ -1641,11 +1645,11 @@ fn add_target_crate_root( Some((BuildScriptOutput { proc_macro_dylib_path, .. }, has_errors)) => { match proc_macro_dylib_path { Some(path) => Ok((cargo_name.to_owned(), path.clone())), - None if has_errors => Err("failed to build proc-macro".to_owned()), - None => Err("proc-macro crate build data is missing dylib path".to_owned()), + None if has_errors => Err(ProcMacroLoadingError::FailedToBuild), + None => Err(ProcMacroLoadingError::MissingDylibPath), } } - None => Err("build scripts have not been built".to_owned()), + None => Err(ProcMacroLoadingError::NotYetBuilt), }; proc_macros.insert(crate_id, proc_macro); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 740fcd81ea9..f97bf832442 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -75,8 +75,12 @@ impl Tester { }; let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); - let loaded_sysroot = - sysroot.load_workspace(&RustSourceWorkspaceConfig::default_cargo(), &path, &|_| ()); + let loaded_sysroot = sysroot.load_workspace( + &RustSourceWorkspaceConfig::default_cargo(), + false, + &path, + &|_| (), + ); if let Some(loaded_sysroot) = loaded_sysroot { sysroot.set_workspace(loaded_sysroot); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e716d140752..51d4c29aa74 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1526,7 +1526,7 @@ impl Config { CompletionConfig { enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(), enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned() - && self.caps.completion_item_edit_resolve(), + && self.caps.has_completion_item_resolve_additionalTextEdits(), enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(), enable_auto_iter: *self.completion_autoIter_enable(source_root), enable_auto_await: *self.completion_autoAwait_enable(source_root), @@ -2355,10 +2355,6 @@ impl Config { .and_then(|it| it.version.as_ref()) } - pub fn client_is_helix(&self) -> bool { - self.client_info.as_ref().map(|it| it.name == "helix").unwrap_or_default() - } - pub fn client_is_neovim(&self) -> bool { self.client_info.as_ref().map(|it| it.name == "Neovim").unwrap_or_default() } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 0e418240db0..91d37bd7c9e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -6,6 +6,7 @@ use std::{fmt, io, process::Command, time::Duration}; use cargo_metadata::PackageId; use crossbeam_channel::{Receiver, Sender, select_biased, unbounded}; use ide_db::FxHashSet; +use itertools::Itertools; use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; use rustc_hash::FxHashMap; use serde::Deserialize as _; @@ -379,7 +380,11 @@ impl FlycheckActor { package_id = msg.package_id.repr, "artifact received" ); - self.report_progress(Progress::DidCheckCrate(msg.target.name)); + self.report_progress(Progress::DidCheckCrate(format!( + "{} ({})", + msg.target.name, + msg.target.kind.iter().format_with(", ", |kind, f| f(&kind)), + ))); let package_id = Arc::new(msg.package_id); if self.diagnostics_cleared_for.insert(package_id.clone()) { tracing::trace!( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index a870232d4a0..62a28a1a685 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -101,7 +101,7 @@ pub(crate) struct GlobalState { pub(crate) last_reported_status: lsp_ext::ServerStatusParams, // proc macros - pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroClient>]>, + pub(crate) proc_macro_clients: Arc<[Option<anyhow::Result<ProcMacroClient>>]>, pub(crate) build_deps_changed: bool, // Flycheck diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs index 40d05567fcc..aea116e647d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs @@ -6,7 +6,7 @@ use std::{ use ide_db::base_db::{ DbPanicContext, - salsa::{self, Cancelled, UnexpectedCycle}, + salsa::{self, Cancelled}, }; use lsp_server::{ExtractError, Response, ResponseError}; use serde::{Serialize, de::DeserializeOwned}; @@ -350,9 +350,6 @@ where if let Some(panic_message) = panic_message { message.push_str(": "); message.push_str(panic_message); - } else if let Some(cycle) = panic.downcast_ref::<UnexpectedCycle>() { - tracing::error!("{cycle}"); - message.push_str(": unexpected cycle"); } else if let Ok(cancelled) = panic.downcast::<Cancelled>() { tracing::error!("Cancellation propagated out of salsa! This is a bug"); return Err(HandlerCancelledError::Inner(*cancelled)); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs index 04e31f37fd2..f94e7486ff8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs @@ -42,7 +42,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { hover_provider: Some(HoverProviderCapability::Simple(true)), completion_provider: Some(CompletionOptions { resolve_provider: if config.client_is_neovim() { - config.completion_item_edit_resolve().then_some(true) + config.has_completion_item_resolve_additionalTextEdits().then_some(true) } else { Some(config.caps().completions_resolve_provider()) }, @@ -207,8 +207,8 @@ impl ClientCapabilities { serde_json::from_value(self.0.experimental.as_ref()?.get(index)?.clone()).ok() } - /// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports. - pub fn completion_item_edit_resolve(&self) -> bool { + #[allow(non_snake_case)] + pub fn has_completion_item_resolve_additionalTextEdits(&self) -> bool { (|| { Some( self.0 diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 0c0438c4b8f..00cf890510d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -783,9 +783,14 @@ impl GlobalState { DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it), }; - let handle = - discover.spawn(arg, &std::env::current_dir().unwrap()).unwrap(); - self.discover_handle = Some(handle); + let handle = discover.spawn( + arg, + &std::env::current_dir() + .expect("Failed to get cwd during project discovery"), + ); + self.discover_handle = Some(handle.unwrap_or_else(|e| { + panic!("Failed to spawn project discovery command: {e}") + })); } } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 133d5a6cf7a..e798aa6a8a6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -18,7 +18,7 @@ use std::{iter, mem}; use hir::{ChangeWithProcMacros, ProcMacrosBuilder, db::DefDatabase}; use ide_db::{ FxHashMap, - base_db::{CrateGraphBuilder, ProcMacroPaths, salsa::Durability}, + base_db::{CrateGraphBuilder, ProcMacroLoadingError, ProcMacroPaths, salsa::Durability}, }; use itertools::Itertools; use load_cargo::{ProjectFolders, load_proc_macro}; @@ -194,8 +194,7 @@ impl GlobalState { format_to!(message, "{e}"); }); - let proc_macro_clients = - self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None)); + let proc_macro_clients = self.proc_macro_clients.iter().chain(iter::repeat(&None)); for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) { if let ProjectWorkspaceKind::Cargo { error: Some(error), .. } @@ -252,7 +251,8 @@ impl GlobalState { message.push_str("\n\n"); } } - _ => (), + // sysroot was explicitly not set so we didn't discover a server + None => {} } } } @@ -419,14 +419,11 @@ impl GlobalState { }; let mut builder = ProcMacrosBuilder::default(); - let proc_macro_clients = proc_macro_clients - .iter() - .map(|res| res.as_ref().map_err(|e| e.to_string())) - .chain(iter::repeat_with(|| Err("proc-macro-srv is not running".into()))); + let proc_macro_clients = proc_macro_clients.iter().chain(iter::repeat(&None)); for (client, paths) in proc_macro_clients.zip(paths) { for (crate_id, res) in paths.iter() { let expansion_res = match client { - Ok(client) => match res { + Some(Ok(client)) => match res { Ok((crate_name, path)) => { progress(format!("loading proc-macros: {path}")); let ignored_proc_macros = ignored_proc_macros @@ -438,9 +435,14 @@ impl GlobalState { load_proc_macro(client, path, ignored_proc_macros) } - Err(e) => Err((e.clone(), true)), + Err(e) => Err(e.clone()), }, - Err(ref e) => Err((e.clone(), true)), + Some(Err(e)) => Err(ProcMacroLoadingError::ProcMacroSrvError( + e.to_string().into_boxed_str(), + )), + None => Err(ProcMacroLoadingError::ProcMacroSrvError( + "proc-macro-srv is not running".into(), + )), }; builder.insert(*crate_id, expansion_res) } @@ -655,7 +657,10 @@ impl GlobalState { self.proc_macro_clients = Arc::from_iter(self.workspaces.iter().map(|ws| { let path = match self.config.proc_macro_srv() { Some(path) => path, - None => ws.find_sysroot_proc_macro_srv()?, + None => match ws.find_sysroot_proc_macro_srv()? { + Ok(path) => path, + Err(e) => return Some(Err(e)), + }, }; let env: FxHashMap<_, _> = match &ws.kind { @@ -682,14 +687,14 @@ impl GlobalState { }; info!("Using proc-macro server at {path}"); - ProcMacroClient::spawn(&path, &env).map_err(|err| { + Some(ProcMacroClient::spawn(&path, &env).map_err(|err| { tracing::error!( "Failed to run proc-macro server from path {path}, error: {err:?}", ); anyhow::format_err!( "Failed to run proc-macro server from path {path}, error: {err:?}", ) - }) + })) })) } @@ -753,14 +758,14 @@ impl GlobalState { change.set_proc_macros( crate_graph .iter() - .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true)))) + .map(|id| (id, Err(ProcMacroLoadingError::NotYetBuilt))) .collect(), ); } else { change.set_proc_macros( crate_graph .iter() - .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false)))) + .map(|id| (id, Err(ProcMacroLoadingError::Disabled))) .collect(), ); } diff --git a/src/tools/rust-analyzer/crates/span/src/ast_id.rs b/src/tools/rust-analyzer/crates/span/src/ast_id.rs index 8e959711981..121d2e33243 100644 --- a/src/tools/rust-analyzer/crates/span/src/ast_id.rs +++ b/src/tools/rust-analyzer/crates/span/src/ast_id.rs @@ -107,9 +107,10 @@ impl fmt::Debug for ErasedFileAstId { } #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +#[repr(u8)] enum ErasedFileAstIdKind { /// This needs to not change because it's depended upon by the proc macro server. - Fixup, + Fixup = 0, // The following are associated with `ErasedHasNameFileAstId`. Enum, Struct, @@ -413,9 +414,9 @@ impl ErasedAstIdNextIndexMap { } macro_rules! register_enum_ast_id { - (impl AstIdNode for $($ident:ident),+ ) => { + (impl $AstIdNode:ident for $($ident:ident),+ ) => { $( - impl AstIdNode for ast::$ident {} + impl $AstIdNode for ast::$ident {} )+ }; } @@ -426,9 +427,9 @@ register_enum_ast_id! { } macro_rules! register_has_name_ast_id { - (impl AstIdNode for $($ident:ident = $name_method:ident),+ ) => { + (impl $AstIdNode:ident for $($ident:ident = $name_method:ident),+ ) => { $( - impl AstIdNode for ast::$ident {} + impl $AstIdNode for ast::$ident {} )+ fn has_name_ast_id(node: &SyntaxNode, index_map: &mut ErasedAstIdNextIndexMap) -> Option<ErasedFileAstId> { @@ -472,9 +473,9 @@ register_has_name_ast_id! { } macro_rules! register_assoc_item_ast_id { - (impl AstIdNode for $($ident:ident = $name_callback:expr),+ ) => { + (impl $AstIdNode:ident for $($ident:ident = $name_callback:expr),+ ) => { $( - impl AstIdNode for ast::$ident {} + impl $AstIdNode for ast::$ident {} )+ fn assoc_item_ast_id( diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index 7bb88ac3658..aef3fbf0517 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -97,6 +97,7 @@ const _: () = { const LOCATION: salsa::plumbing::Location = salsa::plumbing::Location { file: file!(), line: line!() }; const DEBUG_NAME: &'static str = "SyntaxContextData"; + const REVISIONS: std::num::NonZeroUsize = std::num::NonZeroUsize::MAX; type Fields<'a> = SyntaxContextData; type Struct<'a> = SyntaxContext; } @@ -108,7 +109,9 @@ const _: () = { static CACHE: zalsa_::IngredientCache<zalsa_struct_::IngredientImpl<SyntaxContext>> = zalsa_::IngredientCache::new(); CACHE.get_or_create(db.zalsa(), || { - db.zalsa().add_or_lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() + db.zalsa() + .lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() + .get_or_create() }) } } @@ -130,9 +133,12 @@ const _: () = { type MemoIngredientMap = salsa::plumbing::MemoIngredientSingletonIndex; fn lookup_or_create_ingredient_index( - aux: &salsa::plumbing::Zalsa, + zalsa: &salsa::plumbing::Zalsa, ) -> salsa::plumbing::IngredientIndices { - aux.add_or_lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>().into() + zalsa + .lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>() + .get_or_create() + .into() } #[inline] @@ -326,14 +332,14 @@ impl<'db> SyntaxContext { None } else { // SAFETY: By our invariant, this is either a root (which we verified it's not) or a valid `salsa::Id`. - unsafe { Some(salsa::Id::from_u32(self.0)) } + unsafe { Some(salsa::Id::from_index(self.0)) } } } #[inline] fn from_salsa_id(id: salsa::Id) -> Self { // SAFETY: This comes from a Salsa ID. - unsafe { Self::from_u32(id.as_u32()) } + unsafe { Self::from_u32(id.index()) } } #[inline] diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 955aadaa25d..309332873cb 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -842,9 +842,10 @@ pub fn ref_pat(pat: ast::Pat) -> ast::RefPat { } pub fn match_arm(pat: ast::Pat, guard: Option<ast::MatchGuard>, expr: ast::Expr) -> ast::MatchArm { + let comma_str = if expr.is_block_like() { "" } else { "," }; return match guard { - Some(guard) => from_text(&format!("{pat} {guard} => {expr}")), - None => from_text(&format!("{pat} => {expr}")), + Some(guard) => from_text(&format!("{pat} {guard} => {expr}{comma_str}")), + None => from_text(&format!("{pat} => {expr}{comma_str}")), }; fn from_text(text: &str) -> ast::MatchArm { @@ -877,7 +878,7 @@ pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::Mat let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| { let needs_comma = arm.comma_token().is_none() && arm.expr().is_none_or(|it| !it.is_block_like()); - let comma = if needs_comma { "," } else { "" }; + let comma = if needs_comma && arm.comma_token().is_none() { "," } else { "" }; let arm = arm.syntax(); format_to_acc!(acc, " {arm}{comma}\n") }); diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index 429e51ba362..17cc5f9c057 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -1212,6 +1212,43 @@ impl SyntaxFactory { ast } + pub fn attr_outer(&self, meta: ast::Meta) -> ast::Attr { + let ast = make::attr_outer(meta.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(meta.syntax().clone(), ast.meta().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn attr_inner(&self, meta: ast::Meta) -> ast::Attr { + let ast = make::attr_inner(meta.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(meta.syntax().clone(), ast.meta().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn meta_token_tree(&self, path: ast::Path, tt: ast::TokenTree) -> ast::Meta { + let ast = make::meta_token_tree(path.clone(), tt.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone()); + builder.map_node(tt.syntax().clone(), ast.token_tree().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn token_tree( &self, delimiter: SyntaxKind, @@ -1242,6 +1279,10 @@ impl SyntaxFactory { pub fn whitespace(&self, text: &str) -> SyntaxToken { make::tokens::whitespace(text) } + + pub fn ident(&self, text: &str) -> SyntaxToken { + make::tokens::ident(text) + } } // `ext` constructors diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 31caf618be9..3fa584850f7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -435,7 +435,7 @@ mod tests { _ => { let var_name = 2 + 2; (var_name, true) - }"#]]; + },"#]]; expect.assert_eq(&edit.new_root.to_string()); assert_eq!(edit.find_annotation(placeholder_snippet).len(), 2); diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs index 1d821e96e55..e830c6a7cf6 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs @@ -435,14 +435,16 @@ impl MiniCore { continue; } - let mut active_line_region = false; - let mut inactive_line_region = false; + let mut active_line_region = 0; + let mut inactive_line_region = 0; if let Some(idx) = trimmed.find("// :!") { - inactive_line_region = true; - inactive_regions.push(&trimmed[idx + "// :!".len()..]); + let regions = trimmed[idx + "// :!".len()..].split(", "); + inactive_line_region += regions.clone().count(); + inactive_regions.extend(regions); } else if let Some(idx) = trimmed.find("// :") { - active_line_region = true; - active_regions.push(&trimmed[idx + "// :".len()..]); + let regions = trimmed[idx + "// :".len()..].split(", "); + active_line_region += regions.clone().count(); + active_regions.extend(regions); } let mut keep = true; @@ -462,11 +464,11 @@ impl MiniCore { if keep { buf.push_str(line); } - if active_line_region { - active_regions.pop().unwrap(); + if active_line_region > 0 { + active_regions.drain(active_regions.len() - active_line_region..); } - if inactive_line_region { - inactive_regions.pop().unwrap(); + if inactive_line_region > 0 { + inactive_regions.drain(inactive_regions.len() - active_line_region..); } } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index d48063fb86f..dc1eba1a1ab 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -11,10 +11,13 @@ //! add: //! asm: //! assert: +//! as_mut: sized //! as_ref: sized //! async_fn: fn, tuple, future, copy //! bool_impl: option, fn //! builtin_impls: +//! borrow: sized +//! borrow_mut: borrow //! cell: copy, drop //! clone: sized //! coerce_pointee: derive, sized, unsize, coerce_unsized, dispatch_from_dyn @@ -228,8 +231,11 @@ pub mod hash { } // region:derive - #[rustc_builtin_macro] - pub macro Hash($item:item) {} + pub(crate) mod derive { + #[rustc_builtin_macro] + pub macro Hash($item:item) {} + } + pub use derive::Hash; // endregion:derive } // endregion:hash @@ -377,11 +383,30 @@ pub mod convert { fn as_ref(&self) -> &T; } // endregion:as_ref + // region:as_mut + pub trait AsMut<T: crate::marker::PointeeSized>: crate::marker::PointeeSized { + fn as_mut(&mut self) -> &mut T; + } + // endregion:as_mut // region:infallible pub enum Infallible {} // endregion:infallible } +pub mod borrow { + // region:borrow + pub trait Borrow<Borrowed: ?Sized> { + fn borrow(&self) -> &Borrowed; + } + // endregion:borrow + + // region:borrow_mut + pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> { + fn borrow_mut(&mut self) -> &mut Borrowed; + } + // endregion:borrow_mut +} + pub mod mem { // region:manually_drop use crate::marker::PointeeSized; @@ -1264,8 +1289,11 @@ pub mod fmt { } // region:derive - #[rustc_builtin_macro] - pub macro Debug($item:item) {} + pub(crate) mod derive { + #[rustc_builtin_macro] + pub macro Debug($item:item) {} + } + pub use derive::Debug; // endregion:derive // region:builtin_impls @@ -1931,6 +1959,8 @@ pub mod prelude { panic, // :panic result::Result::{self, Err, Ok}, // :result str::FromStr, // :str + fmt::derive::Debug, // :fmt, derive + hash::derive::Hash, // :hash, derive }; } diff --git a/src/tools/rust-analyzer/crates/tt/src/iter.rs b/src/tools/rust-analyzer/crates/tt/src/iter.rs index 0418c00174b..3246156f1cb 100644 --- a/src/tools/rust-analyzer/crates/tt/src/iter.rs +++ b/src/tools/rust-analyzer/crates/tt/src/iter.rs @@ -211,6 +211,7 @@ impl<'a, S: Copy> TtIter<'a, S> { } } +#[derive(Clone)] pub enum TtElement<'a, S> { Leaf(&'a Leaf<S>), Subtree(&'a Subtree<S>, TtIter<'a, S>), diff --git a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs index 1228e2e1774..0c41ede5b53 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs @@ -5,8 +5,8 @@ use std::fmt; use fst::{IntoStreamer, Streamer}; -use nohash_hasher::IntMap; -use rustc_hash::FxHashMap; +use indexmap::IndexMap; +use rustc_hash::{FxBuildHasher, FxHashMap}; use crate::{AnchoredPath, FileId, Vfs, VfsPath}; @@ -14,7 +14,7 @@ use crate::{AnchoredPath, FileId, Vfs, VfsPath}; #[derive(Default, Clone, Eq, PartialEq)] pub struct FileSet { files: FxHashMap<VfsPath, FileId>, - paths: IntMap<FileId, VfsPath>, + paths: IndexMap<FileId, VfsPath, FxBuildHasher>, } impl FileSet { diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md index 1ada1cb24c2..8c06f33a9f7 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md @@ -694,24 +694,6 @@ interface CancelFlycheckParams {} Cancels all running flycheck processes. -## Syntax Tree - -**Method:** `rust-analyzer/syntaxTree` - -**Request:** - -```typescript -interface SyntaxTreeParams { - textDocument: TextDocumentIdentifier, - range?: Range, -} -``` - -**Response:** `string` - -Returns textual representation of a parse tree for the file/selected region. -Primarily for debugging, but very useful for all people working on rust-analyzer itself. - ## View Syntax Tree **Method:** `rust-analyzer/viewSyntaxTree` diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index c0df01edd6d..9ee10d86270 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1009,7 +1009,7 @@ impl Rewrite for ast::Ty { }) } } - ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), + ast::TyKind::FnPtr(ref fn_ptr) => rewrite_fn_ptr(fn_ptr, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { rewrite_macro(mac, context, shape, MacroPosition::Expression) @@ -1105,8 +1105,8 @@ impl Rewrite for ast::TyPat { } } -fn rewrite_bare_fn( - bare_fn: &ast::BareFnTy, +fn rewrite_fn_ptr( + fn_ptr: &ast::FnPtrTy, span: Span, context: &RewriteContext<'_>, shape: Shape, @@ -1115,7 +1115,7 @@ fn rewrite_bare_fn( let mut result = String::with_capacity(128); - if let Some(ref lifetime_str) = rewrite_bound_params(context, shape, &bare_fn.generic_params) { + if let Some(ref lifetime_str) = rewrite_bound_params(context, shape, &fn_ptr.generic_params) { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for multiline situation with lots of @@ -1124,10 +1124,10 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(crate::utils::format_safety(bare_fn.safety)); + result.push_str(crate::utils::format_safety(fn_ptr.safety)); result.push_str(&format_extern( - bare_fn.ext, + fn_ptr.ext, context.config.force_explicit_abi(), )); @@ -1145,9 +1145,9 @@ fn rewrite_bare_fn( }; let rewrite = format_function_type( - bare_fn.decl.inputs.iter(), - &bare_fn.decl.output, - bare_fn.decl.c_variadic(), + fn_ptr.decl.inputs.iter(), + &fn_ptr.decl.output, + fn_ptr.decl.c_variadic(), span, context, func_ty_shape, diff --git a/tests/assembly/naked-functions/wasm32.rs b/tests/assembly/naked-functions/wasm32.rs index 5f114246ad5..77547e82041 100644 --- a/tests/assembly/naked-functions/wasm32.rs +++ b/tests/assembly/naked-functions/wasm32.rs @@ -27,18 +27,16 @@ extern "C" fn nop() { naked_asm!("nop") } -// CHECK: .section .text.weak_aligned_nop,"",@ -// CHECK: .weak weak_aligned_nop +// CHECK: .section .text.weak_nop,"",@ +// CHECK: .weak weak_nop // CHECK-LABEL: nop: -// CHECK: .functype weak_aligned_nop () -> () +// CHECK: .functype weak_nop () -> () // CHECK-NOT: .size // CHECK: end_function #[no_mangle] #[unsafe(naked)] #[linkage = "weak"] -// wasm functions cannot be aligned, so this has no effect -#[align(32)] -extern "C" fn weak_aligned_nop() { +extern "C" fn weak_nop() { naked_asm!("nop") } diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index 90073ff3081..fd572910c28 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -1,4 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code +//@ edition: 2024 +//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368) #![crate_type = "lib"] #![feature(fn_align)] @@ -116,3 +118,24 @@ pub fn align_specified_twice_2() {} #[align(32)] #[align(256)] pub fn align_specified_twice_3() {} + +const _: () = { + // CHECK-LABEL: align_unmangled + // CHECK-SAME: align 256 + #[unsafe(no_mangle)] + #[align(32)] + #[align(256)] + extern "C" fn align_unmangled() {} +}; + +unsafe extern "C" { + #[align(256)] + fn align_unmangled(); +} + +// FIXME also check `gen` et al +// CHECK-LABEL: async_align +// CHECK-SAME: align 64 +#[unsafe(no_mangle)] +#[align(64)] +pub async fn async_align() {} diff --git a/tests/codegen/min-function-alignment.rs b/tests/codegen/min-function-alignment.rs index 78989ec5df2..6a3843b0f4f 100644 --- a/tests/codegen/min-function-alignment.rs +++ b/tests/codegen/min-function-alignment.rs @@ -2,6 +2,7 @@ //@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code //@ [align16] compile-flags: -Zmin-function-alignment=16 //@ [align1024] compile-flags: -Zmin-function-alignment=1024 +//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368) #![crate_type = "lib"] #![feature(fn_align)] diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs index f9fce8e5a5d..2648b0213ca 100644 --- a/tests/codegen/naked-fn/aligned.rs +++ b/tests/codegen/naked-fn/aligned.rs @@ -1,6 +1,7 @@ //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 //@ needs-asm-support //@ ignore-arm no "ret" mnemonic +//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368) #![crate_type = "lib"] #![feature(fn_align)] diff --git a/tests/codegen/naked-fn/min-function-alignment.rs b/tests/codegen/naked-fn/min-function-alignment.rs index 59554c1cae5..4ebaacd3eff 100644 --- a/tests/codegen/naked-fn/min-function-alignment.rs +++ b/tests/codegen/naked-fn/min-function-alignment.rs @@ -1,6 +1,7 @@ //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Zmin-function-alignment=16 //@ needs-asm-support //@ ignore-arm no "ret" mnemonic +//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368) #![feature(fn_align)] #![crate_type = "lib"] diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-abort.diff new file mode 100644 index 00000000000..8c5e6a9e827 --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-abort.diff @@ -0,0 +1,101 @@ +- // MIR for `borrow_in_loop` before CopyProp ++ // MIR for `borrow_in_loop` after CopyProp + + fn borrow_in_loop() -> () { + let mut _0: (); + let mut _1: bool; + let _3: bool; + let mut _4: !; + let mut _5: (); + let mut _7: bool; + let mut _9: bool; + let mut _10: bool; + let mut _11: &bool; + let _12: &bool; + let mut _13: bool; + let mut _14: bool; + let mut _15: bool; + let mut _16: !; + scope 1 { + debug c => _1; + let mut _2: &bool; + let mut _17: &bool; + scope 2 { + debug p => _2; + let _6: bool; + scope 3 { + debug a => _6; + let _8: bool; + scope 4 { + debug b => _8; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _17 = const borrow_in_loop::promoted[0]; + _2 = &(*_17); +- StorageLive(_4); + goto -> bb1; + } + + bb1: { +- StorageLive(_6); + StorageLive(_7); + _7 = copy (*_2); + _6 = Not(move _7); + StorageDead(_7); +- StorageLive(_8); + StorageLive(_9); + _9 = copy (*_2); + _8 = Not(move _9); + StorageDead(_9); +- StorageLive(_10); +- _10 = copy _6; +- _1 = move _10; +- StorageDead(_10); ++ _1 = copy _6; + StorageLive(_11); + StorageLive(_12); + _12 = &_1; + _11 = &(*_12); + _2 = move _11; + StorageDead(_11); + StorageDead(_12); + StorageLive(_13); +- StorageLive(_14); +- _14 = copy _6; +- StorageLive(_15); +- _15 = copy _8; +- _13 = Ne(move _14, move _15); ++ _13 = Ne(copy _6, copy _8); + switchInt(move _13) -> [0: bb3, otherwise: bb2]; + } + + bb2: { +- StorageDead(_15); +- StorageDead(_14); + _0 = const (); + StorageDead(_13); +- StorageDead(_8); +- StorageDead(_6); +- StorageDead(_4); + StorageDead(_2); + StorageDead(_1); + return; + } + + bb3: { +- StorageDead(_15); +- StorageDead(_14); +- _5 = const (); + StorageDead(_13); +- StorageDead(_8); +- StorageDead(_6); + goto -> bb1; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-unwind.diff new file mode 100644 index 00000000000..8c5e6a9e827 --- /dev/null +++ b/tests/mir-opt/copy-prop/borrowed_local.borrow_in_loop.CopyProp.panic-unwind.diff @@ -0,0 +1,101 @@ +- // MIR for `borrow_in_loop` before CopyProp ++ // MIR for `borrow_in_loop` after CopyProp + + fn borrow_in_loop() -> () { + let mut _0: (); + let mut _1: bool; + let _3: bool; + let mut _4: !; + let mut _5: (); + let mut _7: bool; + let mut _9: bool; + let mut _10: bool; + let mut _11: &bool; + let _12: &bool; + let mut _13: bool; + let mut _14: bool; + let mut _15: bool; + let mut _16: !; + scope 1 { + debug c => _1; + let mut _2: &bool; + let mut _17: &bool; + scope 2 { + debug p => _2; + let _6: bool; + scope 3 { + debug a => _6; + let _8: bool; + scope 4 { + debug b => _8; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _17 = const borrow_in_loop::promoted[0]; + _2 = &(*_17); +- StorageLive(_4); + goto -> bb1; + } + + bb1: { +- StorageLive(_6); + StorageLive(_7); + _7 = copy (*_2); + _6 = Not(move _7); + StorageDead(_7); +- StorageLive(_8); + StorageLive(_9); + _9 = copy (*_2); + _8 = Not(move _9); + StorageDead(_9); +- StorageLive(_10); +- _10 = copy _6; +- _1 = move _10; +- StorageDead(_10); ++ _1 = copy _6; + StorageLive(_11); + StorageLive(_12); + _12 = &_1; + _11 = &(*_12); + _2 = move _11; + StorageDead(_11); + StorageDead(_12); + StorageLive(_13); +- StorageLive(_14); +- _14 = copy _6; +- StorageLive(_15); +- _15 = copy _8; +- _13 = Ne(move _14, move _15); ++ _13 = Ne(copy _6, copy _8); + switchInt(move _13) -> [0: bb3, otherwise: bb2]; + } + + bb2: { +- StorageDead(_15); +- StorageDead(_14); + _0 = const (); + StorageDead(_13); +- StorageDead(_8); +- StorageDead(_6); +- StorageDead(_4); + StorageDead(_2); + StorageDead(_1); + return; + } + + bb3: { +- StorageDead(_15); +- StorageDead(_14); +- _5 = const (); + StorageDead(_13); +- StorageDead(_8); +- StorageDead(_6); + goto -> bb1; + } + } + diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff index 40e8c06f357..285cd0f6527 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff @@ -7,14 +7,13 @@ let mut _3: &T; bb0: { -- _2 = copy _1; + _2 = copy _1; _3 = &_1; _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; } bb1: { -- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind unreachable]; -+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind unreachable]; + _0 = opaque::<T>(copy _2) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff index d09c96c0f2b..f189615ea95 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff @@ -7,14 +7,13 @@ let mut _3: &T; bb0: { -- _2 = copy _1; + _2 = copy _1; _3 = &_1; _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; } bb1: { -- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind continue]; -+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind continue]; + _0 = opaque::<T>(copy _2) -> [return: bb2, unwind continue]; } bb2: { diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index 8db19fbd377..68cdc57483a 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -50,10 +50,11 @@ fn compare_address() -> bool { fn borrowed<T: Copy + Freeze>(x: T) -> bool { // CHECK-LABEL: fn borrowed( // CHECK: bb0: { + // CHECK-NEXT: _2 = copy _1; // CHECK-NEXT: _3 = &_1; // CHECK-NEXT: _0 = opaque::<&T>(copy _3) // CHECK: bb1: { - // CHECK-NEXT: _0 = opaque::<T>(copy _1) + // CHECK-NEXT: _0 = opaque::<T>(copy _2) mir! { { let a = x; @@ -94,11 +95,45 @@ fn non_freeze<T: Copy>(x: T) -> bool { } } +/// We must not unify a borrowed local with another that may be written-to before the borrow is +/// read again. As we have no aliasing model yet, this means forbidding unifying borrowed locals. +fn borrow_in_loop() { + // CHECK-LABEL: fn borrow_in_loop( + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug p => [[p:_.*]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK-NOT: &[[a]] + // CHECK-NOT: &[[b]] + // CHECK: [[a]] = Not({{.*}}); + // CHECK-NOT: &[[a]] + // CHECK-NOT: &[[b]] + // CHECK: [[b]] = Not({{.*}}); + // CHECK-NOT: &[[a]] + // CHECK-NOT: &[[b]] + // CHECK: &[[c]] + // CHECK-NOT: &[[a]] + // CHECK-NOT: &[[b]] + let mut c; + let mut p = &false; + loop { + let a = !*p; + let b = !*p; + c = a; + p = &c; + if a != b { + return; + } + } +} + fn main() { assert!(!compare_address()); non_freeze(5); + borrow_in_loop(); } // EMIT_MIR borrowed_local.compare_address.CopyProp.diff // EMIT_MIR borrowed_local.borrowed.CopyProp.diff // EMIT_MIR borrowed_local.non_freeze.CopyProp.diff +// EMIT_MIR borrowed_local.borrow_in_loop.CopyProp.diff diff --git a/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff b/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff index eab06b1ba1e..baa71501047 100644 --- a/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff @@ -16,11 +16,10 @@ _3 = const 'b'; _5 = copy _3; _6 = &_3; -- _4 = copy _5; + _4 = copy _5; (*_1) = copy (*_6); _6 = &_5; -- _7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable]; -+ _7 = dump_var::<char>(copy _5) -> [return: bb1, unwind unreachable]; + _7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/copy-prop/write_to_borrowed.rs b/tests/mir-opt/copy-prop/write_to_borrowed.rs index 58809749103..05aa2fba18d 100644 --- a/tests/mir-opt/copy-prop/write_to_borrowed.rs +++ b/tests/mir-opt/copy-prop/write_to_borrowed.rs @@ -27,13 +27,13 @@ fn main() { _5 = _3; // CHECK-NEXT: _6 = &_3; _6 = &_3; - // CHECK-NOT: {{_.*}} = {{_.*}}; + // CHECK-NEXT: _4 = copy _5; _4 = _5; // CHECK-NEXT: (*_1) = copy (*_6); *_1 = *_6; // CHECK-NEXT: _6 = &_5; _6 = &_5; - // CHECK-NEXT: _7 = dump_var::<char>(copy _5) + // CHECK-NEXT: _7 = dump_var::<char>(copy _4) Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { Return() } diff --git a/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-abort.diff b/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-abort.diff new file mode 100644 index 00000000000..db72e84f24b --- /dev/null +++ b/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-abort.diff @@ -0,0 +1,27 @@ +- // MIR for `Trait::a` before Inline ++ // MIR for `Trait::a` after Inline + + fn Trait::a(_1: &Self) -> () { + debug self => _1; + let mut _0: (); + let _2: (); + let mut _3: &(); + let _4: (); + let mut _5: &(); + + bb0: { + StorageLive(_2); + StorageLive(_3); + _5 = const <Self as Trait>::a::promoted[0]; + _3 = &(*_5); + _2 = <() as Trait>::b(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-unwind.diff b/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-unwind.diff new file mode 100644 index 00000000000..aad5a62f82d --- /dev/null +++ b/tests/mir-opt/inline_default_trait_body.Trait-a.Inline.panic-unwind.diff @@ -0,0 +1,27 @@ +- // MIR for `Trait::a` before Inline ++ // MIR for `Trait::a` after Inline + + fn Trait::a(_1: &Self) -> () { + debug self => _1; + let mut _0: (); + let _2: (); + let mut _3: &(); + let _4: (); + let mut _5: &(); + + bb0: { + StorageLive(_2); + StorageLive(_3); + _5 = const <Self as Trait>::a::promoted[0]; + _3 = &(*_5); + _2 = <() as Trait>::b(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-abort.diff b/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-abort.diff new file mode 100644 index 00000000000..b5ca892077e --- /dev/null +++ b/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-abort.diff @@ -0,0 +1,27 @@ +- // MIR for `Trait::b` before Inline ++ // MIR for `Trait::b` after Inline + + fn Trait::b(_1: &Self) -> () { + debug self => _1; + let mut _0: (); + let _2: (); + let mut _3: &(); + let _4: (); + let mut _5: &(); + + bb0: { + StorageLive(_2); + StorageLive(_3); + _5 = const <Self as Trait>::b::promoted[0]; + _3 = &(*_5); + _2 = <() as Trait>::a(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-unwind.diff b/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-unwind.diff new file mode 100644 index 00000000000..1f51d2e4b5e --- /dev/null +++ b/tests/mir-opt/inline_default_trait_body.Trait-b.Inline.panic-unwind.diff @@ -0,0 +1,27 @@ +- // MIR for `Trait::b` before Inline ++ // MIR for `Trait::b` after Inline + + fn Trait::b(_1: &Self) -> () { + debug self => _1; + let mut _0: (); + let _2: (); + let mut _3: &(); + let _4: (); + let mut _5: &(); + + bb0: { + StorageLive(_2); + StorageLive(_3); + _5 = const <Self as Trait>::b::promoted[0]; + _3 = &(*_5); + _2 = <() as Trait>::a(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/inline_default_trait_body.rs b/tests/mir-opt/inline_default_trait_body.rs new file mode 100644 index 00000000000..aeb8031b418 --- /dev/null +++ b/tests/mir-opt/inline_default_trait_body.rs @@ -0,0 +1,19 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// skip-filecheck +//@ test-mir-pass: Inline +//@ edition: 2021 +//@ compile-flags: -Zinline-mir --crate-type=lib + +// EMIT_MIR inline_default_trait_body.Trait-a.Inline.diff +// EMIT_MIR inline_default_trait_body.Trait-b.Inline.diff +pub trait Trait { + fn a(&self) { + ().b(); + } + + fn b(&self) { + ().a(); + } +} + +impl Trait for () {} diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cbdd194afd3..97036745009 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -10,18 +10,18 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 let mut _8: &&usize; let _9: &usize; let mut _10: &&usize; - let mut _13: bool; - let mut _14: &&usize; - let _15: &usize; + let mut _15: bool; let mut _16: &&usize; - let mut _19: bool; - let mut _20: &&usize; - let _21: &usize; - let mut _22: &&usize; + let _17: &usize; + let mut _18: &&usize; let mut _23: bool; let mut _24: &&usize; let _25: &usize; let mut _26: &&usize; + let mut _29: bool; + let mut _30: &&usize; + let _31: &usize; + let mut _32: &&usize; scope 1 { debug a => _4; debug b => _5; @@ -30,39 +30,47 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { debug self => _8; debug other => _10; + let mut _11: &usize; + let mut _12: &usize; scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _4; - debug other => _6; - let mut _11: usize; - let mut _12: usize; + debug self => _11; + debug other => _12; + let mut _13: usize; + let mut _14: usize; } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _14; - debug other => _16; + debug self => _16; + debug other => _18; + let mut _19: &usize; + let mut _20: &usize; scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _7; - debug other => _5; - let mut _17: usize; - let mut _18: usize; + debug self => _19; + debug other => _20; + let mut _21: usize; + let mut _22: usize; } } scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _20; - debug other => _22; + debug self => _24; + debug other => _26; + let mut _27: &usize; + let mut _28: &usize; scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _6; - debug other => _4; + debug self => _27; + debug other => _28; } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _24; - debug other => _26; + debug self => _30; + debug other => _32; + let mut _33: &usize; + let mut _34: &usize; scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _5; - debug other => _7; - let mut _27: usize; - let mut _28: usize; + debug self => _33; + debug other => _34; + let mut _35: usize; + let mut _36: usize; } } } @@ -73,17 +81,23 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 _5 = &((*_3).1: usize); _6 = &((*_3).2: usize); _7 = &((*_3).3: usize); - StorageLive(_13); + StorageLive(_15); StorageLive(_8); _8 = &_4; StorageLive(_10); StorageLive(_9); _9 = copy _6; _10 = &_9; - _11 = copy ((*_3).0: usize); - _12 = copy ((*_3).2: usize); - _13 = Le(copy _11, copy _12); - switchInt(move _13) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_12); + _11 = copy _4; + _12 = copy _6; + _13 = copy ((*_3).0: usize); + _14 = copy ((*_3).2: usize); + _15 = Le(copy _13, copy _14); + StorageDead(_12); + StorageDead(_11); + switchInt(move _15) -> [0: bb1, otherwise: bb2]; } bb1: { @@ -97,89 +111,107 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 StorageDead(_9); StorageDead(_10); StorageDead(_8); - StorageLive(_19); - StorageLive(_14); - _14 = &_7; + StorageLive(_23); StorageLive(_16); - StorageLive(_15); - _15 = copy _5; - _16 = &_15; - StorageLive(_17); - _17 = copy ((*_3).3: usize); + _16 = &_7; StorageLive(_18); - _18 = copy ((*_3).1: usize); - _19 = Le(move _17, move _18); - StorageDead(_18); - StorageDead(_17); - switchInt(move _19) -> [0: bb3, otherwise: bb8]; + StorageLive(_17); + _17 = copy _5; + _18 = &_17; + StorageLive(_19); + StorageLive(_20); + _19 = copy _7; + _20 = copy _5; + StorageLive(_21); + _21 = copy ((*_3).3: usize); + StorageLive(_22); + _22 = copy ((*_3).1: usize); + _23 = Le(move _21, move _22); + StorageDead(_22); + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + switchInt(move _23) -> [0: bb3, otherwise: bb8]; } bb3: { - StorageDead(_15); + StorageDead(_17); + StorageDead(_18); StorageDead(_16); - StorageDead(_14); goto -> bb4; } bb4: { - StorageLive(_23); - StorageLive(_20); - _20 = &_6; - StorageLive(_22); - StorageLive(_21); - _21 = copy _4; - _22 = &_21; - _23 = Le(copy _12, copy _11); - switchInt(move _23) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); - _0 = const false; - goto -> bb7; - } - - bb6: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); + StorageLive(_29); StorageLive(_24); - _24 = &_5; + _24 = &_6; StorageLive(_26); StorageLive(_25); - _25 = copy _7; + _25 = copy _4; _26 = &_25; StorageLive(_27); - _27 = copy ((*_3).1: usize); StorageLive(_28); - _28 = copy ((*_3).3: usize); - _0 = Le(move _27, move _28); + _27 = copy _6; + _28 = copy _4; + _29 = Le(copy _14, copy _13); StorageDead(_28); StorageDead(_27); + switchInt(move _29) -> [0: bb5, otherwise: bb6]; + } + + bb5: { StorageDead(_25); StorageDead(_26); StorageDead(_24); + _0 = const false; + goto -> bb7; + } + + bb6: { + StorageDead(_25); + StorageDead(_26); + StorageDead(_24); + StorageLive(_30); + _30 = &_5; + StorageLive(_32); + StorageLive(_31); + _31 = copy _7; + _32 = &_31; + StorageLive(_33); + StorageLive(_34); + _33 = copy _5; + _34 = copy _7; + StorageLive(_35); + _35 = copy ((*_3).1: usize); + StorageLive(_36); + _36 = copy ((*_3).3: usize); + _0 = Le(move _35, move _36); + StorageDead(_36); + StorageDead(_35); + StorageDead(_34); + StorageDead(_33); + StorageDead(_31); + StorageDead(_32); + StorageDead(_30); goto -> bb7; } bb7: { - StorageDead(_23); + StorageDead(_29); goto -> bb9; } bb8: { - StorageDead(_15); + StorageDead(_17); + StorageDead(_18); StorageDead(_16); - StorageDead(_14); _0 = const true; goto -> bb9; } bb9: { - StorageDead(_19); - StorageDead(_13); + StorageDead(_23); + StorageDead(_15); return; } } diff --git a/tests/run-make/linker-warning/bar.rs b/tests/run-make/linker-warning/bar.rs new file mode 100644 index 00000000000..366816f31ea --- /dev/null +++ b/tests/run-make/linker-warning/bar.rs @@ -0,0 +1,2 @@ +#[repr(C)] +pub struct Bar(u32); diff --git a/tests/run-make/linker-warning/foo.rs b/tests/run-make/linker-warning/foo.rs new file mode 100644 index 00000000000..de3390c8c26 --- /dev/null +++ b/tests/run-make/linker-warning/foo.rs @@ -0,0 +1,2 @@ +#[repr(C)] +pub struct Foo(u32); diff --git a/tests/run-make/linker-warning/main.rs b/tests/run-make/linker-warning/main.rs index f328e4d9d04..fef5e3eb144 100644 --- a/tests/run-make/linker-warning/main.rs +++ b/tests/run-make/linker-warning/main.rs @@ -1 +1,10 @@ -fn main() {} +unsafe extern "C" { + #[cfg(only_foo)] + fn does_not_exist(p: *const u8) -> *const foo::Foo; + #[cfg(not(only_foo))] + fn does_not_exist(p: *const bar::Bar) -> *const foo::Foo; +} + +fn main() { + let _ = unsafe { does_not_exist(core::ptr::null()) }; +} diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 26d03fd2d70..57b68c65930 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -11,6 +11,7 @@ fn run_rustc() -> Rustc { .arg("-Clink-self-contained=-linker") .arg("-Zunstable-options") .arg("-Wlinker-messages") + .args(["--extern", "foo", "--extern", "bar"]) .output("main") .linker("./fake-linker"); if run_make_support::target() == "x86_64-unknown-linux-gnu" { @@ -21,8 +22,10 @@ fn run_rustc() -> Rustc { } fn main() { - // first, compile our linker + // first, compile our linker and our dependencies rustc().arg("fake-linker.rs").output("fake-linker").run(); + rustc().arg("foo.rs").crate_type("rlib").run(); + rustc().arg("bar.rs").crate_type("rlib").run(); // Run rustc with our fake linker, and make sure it shows warnings let warnings = run_rustc().link_arg("run_make_warn").run(); @@ -48,7 +51,8 @@ fn main() { let out = run_rustc().link_arg("run_make_error").run_fail(); out.assert_stderr_contains("fake-linker") .assert_stderr_contains("object files omitted") - .assert_stderr_contains_regex(r"\{") + .assert_stderr_contains("/{libfoo,libbar}.rlib\"") + .assert_stderr_contains("-*}.rlib\"") .assert_stderr_not_contains(r".rcgu.o") .assert_stderr_not_contains_regex(r"lib(/|\\\\)libstd"); @@ -68,6 +72,10 @@ fn main() { .run(); } + // Make sure a single dependency doesn't use brace expansion. + let out1 = run_rustc().cfg("only_foo").link_arg("run_make_error").run_fail(); + out1.assert_stderr_contains("fake-linker").assert_stderr_contains("/libfoo.rlib\""); + // Make sure we show linker warnings even across `-Z no-link` rustc() .arg("-Zno-link") diff --git a/tests/run-make/linker-warning/short-error.txt b/tests/run-make/linker-warning/short-error.txt index 33d03832b7e..5b7c040bc50 100644 --- a/tests/run-make/linker-warning/short-error.txt +++ b/tests/run-make/linker-warning/short-error.txt @@ -1,6 +1,6 @@ error: linking with `./fake-linker` failed: exit status: 1 | - = note: "./fake-linker" "-m64" "/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,librustc_std_workspace_core-*,liballoc-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" + = note: "./fake-linker" "-m64" "/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/build-root/test/run-make/linker-warning/rmake_out/{libfoo,libbar}.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,librustc_std_workspace_core-*,liballoc-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" = note: some arguments are omitted. use `--verbose` to show all linker arguments = note: error: baz diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 15ef583709b..9d83dd9ce1a 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -11,10 +11,9 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::abi::{ diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 64194e72888..c2d1d5d873b 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -13,10 +13,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::ascii::Char; diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs index bb95bedf973..574f7797854 100644 --- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -11,8 +11,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs index e4cc7b104b6..f234c658dfd 100644 --- a/tests/ui-fulldeps/stable-mir/check_attribute.rs +++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs @@ -9,10 +9,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::{CrateDef, CrateItems}; diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs index f9559d9958d..748c2088a30 100644 --- a/tests/ui-fulldeps/stable-mir/check_binop.rs +++ b/tests/ui-fulldeps/stable-mir/check_binop.rs @@ -9,10 +9,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::mir::mono::Instance; diff --git a/tests/ui-fulldeps/stable-mir/check_coroutine_body.rs b/tests/ui-fulldeps/stable-mir/check_coroutine_body.rs index 67773492958..2af32afc1f7 100644 --- a/tests/ui-fulldeps/stable-mir/check_coroutine_body.rs +++ b/tests/ui-fulldeps/stable-mir/check_coroutine_body.rs @@ -10,10 +10,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs index 6863242f225..d3929c5e48b 100644 --- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs @@ -10,10 +10,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::CrateDef; diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs index f86a8e0ae61..101e7eb9121 100644 --- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs +++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs @@ -11,8 +11,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index ab741378bb7..65db50ee3ff 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -10,8 +10,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs index 398024c4ff0..2947d51b63b 100644 --- a/tests/ui-fulldeps/stable-mir/check_foreign.rs +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -10,8 +10,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_span; diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index b19e5b033c4..9b1e4176531 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -10,8 +10,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index 52424857dc1..2fce367c7a0 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -14,10 +14,10 @@ extern crate rustc_middle; extern crate rustc_hir; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::mir::mono::{Instance, InstanceKind}; diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index d1124c75a89..20b9e86ff92 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -10,8 +10,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs index 16e8c0339ed..bb5cd49e1b0 100644 --- a/tests/ui-fulldeps/stable-mir/check_normalization.rs +++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs @@ -9,8 +9,7 @@ #![feature(rustc_private)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index fcf04a1fc3a..73ba0ea23c9 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -10,10 +10,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::CrateDef; diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index 9087c1cf450..460f1b9e963 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -11,10 +11,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::mir::alloc::GlobalAlloc; diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index 18b9e32e4e8..1a21757d038 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -11,10 +11,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::mir::{ diff --git a/tests/ui-fulldeps/stable-mir/check_variant.rs b/tests/ui-fulldeps/stable-mir/check_variant.rs index b0de3369830..4cff57308f6 100644 --- a/tests/ui-fulldeps/stable-mir/check_variant.rs +++ b/tests/ui-fulldeps/stable-mir/check_variant.rs @@ -11,10 +11,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/closure-generic-body.rs b/tests/ui-fulldeps/stable-mir/closure-generic-body.rs index 2a23345a9d3..6b3447e5839 100644 --- a/tests/ui-fulldeps/stable-mir/closure-generic-body.rs +++ b/tests/ui-fulldeps/stable-mir/closure-generic-body.rs @@ -10,10 +10,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/closure_body.rs b/tests/ui-fulldeps/stable-mir/closure_body.rs index 7ed0dabd2c3..a1c97e7549b 100644 --- a/tests/ui-fulldeps/stable-mir/closure_body.rs +++ b/tests/ui-fulldeps/stable-mir/closure_body.rs @@ -10,10 +10,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index 19b9c8b7de5..d577de48c55 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -10,10 +10,10 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 7fc4edafb93..fd7c2032b6d 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -11,10 +11,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use rustc_hir::def::DefKind; diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 103c97bc48e..f8104287700 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -11,10 +11,10 @@ extern crate rustc_hir; extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; +#[macro_use] extern crate stable_mir; use stable_mir::ItemKind; diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index 0519b9de680..287f4353d51 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -10,15 +10,14 @@ #![feature(rustc_private)] #![feature(assert_matches)] -#[macro_use] -extern crate rustc_smir; extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_middle; +#[macro_use] extern crate stable_mir; use rustc_middle::ty::TyCtxt; -use rustc_smir::rustc_internal; +use stable_mir::rustc_internal; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs index 0b39ec05002..c2f00e56c2c 100644 --- a/tests/ui-fulldeps/stable-mir/smir_serde.rs +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -9,13 +9,13 @@ #![feature(rustc_private)] #![feature(assert_matches)] -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_middle; extern crate serde; extern crate serde_json; +#[macro_use] extern crate stable_mir; use rustc_middle::ty::TyCtxt; diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index caf71de2556..46f85a992ef 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -10,8 +10,7 @@ #![feature(assert_matches)] extern crate rustc_middle; -#[macro_use] -extern crate rustc_smir; + extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.generic.stderr index 52351a2c260..3b29efc8102 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -89,7 +89,7 @@ error: fn_abi_of(test) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:23:1 + --> $DIR/debug.rs:27:1 | LL | fn test(_x: u8) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:29:1 + --> $DIR/debug.rs:33:1 | LL | type TestFnPtr = fn(bool) -> u8; | ^^^^^^^^^^^^^^ @@ -263,13 +263,13 @@ error: fn_abi_of(test_generic) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:32:1 + --> $DIR/debug.rs:36:1 | LL | fn test_generic<T>(_x: *const T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions - --> $DIR/debug.rs:35:1 + --> $DIR/debug.rs:39:1 | LL | const C: () = (); | ^^^^^^^^^^^ @@ -419,7 +419,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:51:1 + --> $DIR/debug.rs:55:1 | LL | type TestAbiNe = (fn(u8), fn(u32)); | ^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:54:1 + --> $DIR/debug.rs:58:1 | LL | type TestAbiNeLarger = (fn([u8; 32]), fn([u32; 32])); | ^^^^^^^^^^^^^^^^^^^^ @@ -720,7 +720,7 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:57:1 + --> $DIR/debug.rs:61:1 | LL | type TestAbiNeFloat = (fn(f32), fn(u32)); | ^^^^^^^^^^^^^^^^^^^ @@ -870,13 +870,13 @@ error: ABIs are not compatible conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:61:1 + --> $DIR/debug.rs:65:1 | LL | type TestAbiNeSign = (fn(i32), fn(u32)); | ^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/debug.rs:64:46 + --> $DIR/debug.rs:68:46 | LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -885,13 +885,13 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = note: only the last element of a tuple may have a dynamically sized type error: unrecognized argument - --> $DIR/debug.rs:66:13 + --> $DIR/debug.rs:70:13 | LL | #[rustc_abi("assert_eq")] | ^^^^^^^^^^^ error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions - --> $DIR/debug.rs:39:5 + --> $DIR/debug.rs:43:5 | LL | const C: () = (); | ^^^^^^^^^^^ @@ -981,7 +981,7 @@ error: fn_abi_of(assoc_test) = FnAbi { conv: Rust, can_unwind: $SOME_BOOL, } - --> $DIR/debug.rs:44:5 + --> $DIR/debug.rs:48:5 | LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr new file mode 100644 index 00000000000..2417396de2f --- /dev/null +++ b/tests/ui/abi/debug.riscv64.stderr @@ -0,0 +1,991 @@ +error: fn_abi_of(test) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: bool, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + fields: Primitive, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:27:1 + | +LL | fn test(_x: u8) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(TestFnPtr) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: bool, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + fields: Primitive, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:33:1 + | +LL | type TestFnPtr = fn(bool) -> u8; + | ^^^^^^^^^^^^^^ + +error: fn_abi_of(test_generic) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: *const T, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:36:1 + | +LL | fn test_generic<T>(_x: *const T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions + --> $DIR/debug.rs:39:1 + | +LL | const C: () = (); + | ^^^^^^^^^^^ + +error: ABIs are not compatible + left ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + right ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:55:1 + | +LL | type TestAbiNe = (fn(u8), fn(u32)); + | ^^^^^^^^^^^^^^ + +error: ABIs are not compatible + left ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: [u8; 32], + layout: Layout { + size: Size(32 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Array { + stride: Size(1 bytes), + count: 32, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(32 bytes), + pointee_align: Some( + Align(1 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + right ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: [u32; 32], + layout: Layout { + size: Size(128 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Array { + stride: Size(4 bytes), + count: 32, + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Indirect { + attrs: ArgAttributes { + regular: NoAlias | NoCapture | NonNull | NoUndef, + arg_ext: None, + pointee_size: Size(128 bytes), + pointee_align: Some( + Align(4 bytes), + ), + }, + meta_attrs: None, + on_stack: false, + }, + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:58:1 + | +LL | type TestAbiNeLarger = (fn([u8; 32]), fn([u32; 32])); + | ^^^^^^^^^^^^^^^^^^^^ + +error: ABIs are not compatible + left ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: f32, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Float( + F32, + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + right ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:61:1 + | +LL | type TestAbiNeFloat = (fn(f32), fn(u32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: ABIs are not compatible + left ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i32, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + right ABI = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: $FULL, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:65:1 + | +LL | type TestAbiNeSign = (fn(i32), fn(u32)); + | ^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/debug.rs:68:46 + | +LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error: unrecognized argument + --> $DIR/debug.rs:70:13 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^ + +error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions + --> $DIR/debug.rs:43:5 + | +LL | const C: () = (); + | ^^^^^^^^^^^ + +error: fn_abi_of(assoc_test) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: &S, + layout: Layout { + size: $SOME_SIZE, + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: $NON_NULL, + }, + ), + fields: Primitive, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: $NON_NULL, + }, + ), + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoAlias | NonNull | ReadOnly | NoUndef, + arg_ext: None, + pointee_size: Size(2 bytes), + pointee_align: Some( + Align(2 bytes), + ), + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: (), + layout: Layout { + size: Size(0 bytes), + align: AbiAlign { + abi: $SOME_ALIGN, + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: $SOME_ALIGN, + randomization_seed: $SEED, + }, + }, + mode: Ignore, + }, + c_variadic: false, + fixed_count: 1, + conv: Rust, + can_unwind: $SOME_BOOL, + } + --> $DIR/debug.rs:48:5 + | +LL | fn assoc_test(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index 97f5d5fba98..cc1589d8621 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -8,6 +8,10 @@ //@ normalize-stderr: "(valid_range): [1-9]\.\.=(429496729[0-9]|1844674407370955161[0-9])" -> "$1: $$NON_NULL" // Some attributes are only computed for release builds: //@ compile-flags: -O +//@ revisions: generic riscv64 +//@ [riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu +//@ [riscv64] needs-llvm-components: riscv +//@ [generic] ignore-riscv64 #![feature(rustc_attrs)] #![crate_type = "lib"] #![feature(no_core)] diff --git a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr index 64304be9d6b..eaa212c6ce8 100644 --- a/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr +++ b/tests/ui/associated-type-bounds/dedup-normalized-2-higher-ranked.current.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/dedup-normalized-2-higher-ranked.rs:28:5 | LL | impls(rigid); - | ^^^^^ cannot infer type of the type parameter `U` declared on the function `impls` + | ^^^^^ ----- type must be known at this point + | | + | cannot infer type of the type parameter `U` declared on the function `impls` | = note: cannot satisfy `for<'b> <P as Trait>::Rigid: Bound<'b, _>` note: required by a bound in `impls` diff --git a/tests/ui/attributes/fn-align-dyn.rs b/tests/ui/attributes/fn-align-dyn.rs new file mode 100644 index 00000000000..8ba4d5e2897 --- /dev/null +++ b/tests/ui/attributes/fn-align-dyn.rs @@ -0,0 +1,16 @@ +//@ run-pass +//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368) +#![feature(fn_align)] + +trait Test { + #[align(4096)] + fn foo(&self); + + #[align(4096)] + fn foo1(&self); +} + +fn main() { + assert_eq!((<dyn Test>::foo as fn(_) as usize & !1) % 4096, 0); + assert_eq!((<dyn Test>::foo1 as fn(_) as usize & !1) % 4096, 0); +} diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index f5ab9555e56..e06e6116842 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -21,5 +21,29 @@ fn f3() {} #[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on function items fn f4() {} +#[align(-1)] //~ ERROR expected unsuffixed literal, found `-` +fn f5() {} + +#[align(3)] //~ ERROR invalid alignment value: not a power of two +fn f6() {} + +#[align(4usize)] //~ ERROR invalid alignment value: not an unsuffixed integer [E0589] +//~^ ERROR suffixed literals are not allowed in attributes +fn f7() {} + +#[align(16)] +#[align(3)] //~ ERROR invalid alignment value: not a power of two +#[align(16)] +fn f8() {} + #[align(16)] //~ ERROR `#[align(...)]` is not supported on struct items struct S1; + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +const FOO: i32 = 42; + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +mod test {} + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +use ::std::iter; diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index b769d0b457d..af3625b1f3b 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -1,3 +1,17 @@ +error: expected unsuffixed literal, found `-` + --> $DIR/malformed-fn-align.rs:24:9 + | +LL | #[align(-1)] + | ^ + +error: suffixed literals are not allowed in attributes + --> $DIR/malformed-fn-align.rs:30:9 + | +LL | #[align(4usize)] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + error[E0539]: malformed `align` attribute input --> $DIR/malformed-fn-align.rs:5:5 | @@ -37,6 +51,24 @@ error[E0589]: invalid alignment value: not a power of two LL | #[align(0)] | ^ +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-fn-align.rs:27:9 + | +LL | #[align(3)] + | ^ + +error[E0589]: invalid alignment value: not an unsuffixed integer + --> $DIR/malformed-fn-align.rs:30:9 + | +LL | #[align(4usize)] + | ^^^^^^ + +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-fn-align.rs:35:9 + | +LL | #[align(3)] + | ^ + error: `#[repr(align(...))]` is not supported on function items --> $DIR/malformed-fn-align.rs:21:8 | @@ -50,7 +82,7 @@ LL | #[repr(align(16))] | ^^^^^^^^^ error: `#[align(...)]` is not supported on struct items - --> $DIR/malformed-fn-align.rs:24:1 + --> $DIR/malformed-fn-align.rs:39:1 | LL | #[align(16)] | ^^^^^^^^^^^^ @@ -61,7 +93,31 @@ LL - #[align(16)] LL + #[repr(align(16))] | -error: aborting due to 7 previous errors +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:42:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | const FOO: i32 = 42; + | -------------------- not a function item + +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:45:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | mod test {} + | ----------- not a function item + +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:48:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | use ::std::iter; + | ---------------- not a function item + +error: aborting due to 15 previous errors Some errors have detailed explanations: E0539, E0589, E0805. For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/malformed-reprs.rs b/tests/ui/attributes/malformed-reprs.rs new file mode 100644 index 00000000000..4f99239d21b --- /dev/null +++ b/tests/ui/attributes/malformed-reprs.rs @@ -0,0 +1,14 @@ +// Tests a few different invalid repr attributes + +// This is a regression test for https://github.com/rust-lang/rust/issues/143522 +#![repr] +//~^ ERROR malformed `repr` attribute input [E0539] +//~| ERROR `repr` attribute cannot be used at crate level + +// This is a regression test for https://github.com/rust-lang/rust/issues/143479 +#[repr(align(0))] +//~^ ERROR invalid `repr(align)` attribute: not a power of two +//~| ERROR unsupported representation for zero-variant enum [E0084] +enum Foo {} + +fn main() {} diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr new file mode 100644 index 00000000000..c39c98dde31 --- /dev/null +++ b/tests/ui/attributes/malformed-reprs.stderr @@ -0,0 +1,43 @@ +error[E0539]: malformed `repr` attribute input + --> $DIR/malformed-reprs.rs:4:1 + | +LL | #![repr] + | ^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + +error[E0589]: invalid `repr(align)` attribute: not a power of two + --> $DIR/malformed-reprs.rs:9:14 + | +LL | #[repr(align(0))] + | ^ + +error: `repr` attribute cannot be used at crate level + --> $DIR/malformed-reprs.rs:4:1 + | +LL | #![repr] + | ^^^^^^^^ +... +LL | enum Foo {} + | --- the inner attribute doesn't annotate this enum + | +help: perhaps you meant to use an outer attribute + | +LL - #![repr] +LL + #[repr] + | + +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/malformed-reprs.rs:9:1 + | +LL | #[repr(align(0))] + | ^^^^^^^^^^^^^^^^^ +... +LL | enum Foo {} + | -------- zero-variant enum + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0084, E0539, E0589. +For more information about an error, try `rustc --explain E0084`. diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr index 4f42afed81d..7098850e978 100644 --- a/tests/ui/const-generics/defaults/wfness.stderr +++ b/tests/ui/const-generics/defaults/wfness.stderr @@ -12,6 +12,14 @@ LL | (): Trait<N>; | = help: the trait `Trait<2>` is not implemented for `()` but trait `Trait<3>` is implemented for it +note: required by a bound in `WhereClause` + --> $DIR/wfness.rs:8:9 + | +LL | struct WhereClause<const N: u8 = 2> + | ----------- required by a bound in this struct +LL | where +LL | (): Trait<N>; + | ^^^^^^^^ required by this bound in `WhereClause` error[E0277]: the trait bound `(): Trait<1>` is not satisfied --> $DIR/wfness.rs:18:13 diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr index 4ab80cec58d..3763cd738a8 100644 --- a/tests/ui/const-generics/infer/issue-77092.stderr +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -20,7 +20,7 @@ error[E0284]: type annotations needed LL | println!("{:?}", take_array_from_mut(&mut arr, i)); | ---- ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` | | - | type must be known at this point + | required by this formatting parameter | = note: required for `[i32; _]` to implement `Debug` = note: 1 redundant requirement hidden diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 1620bf72922..49c666f498f 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -121,21 +121,6 @@ LL - #![rustc_main] LL + #[rustc_main] | -error: `path` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 - | -LL | #![path = "3800"] - | ^^^^^^^^^^^^^^^^^ -... -LL | mod inline { - | ------ the inner attribute doesn't annotate this module - | -help: perhaps you meant to use an outer attribute - | -LL - #![path = "3800"] -LL + #[path = "3800"] - | - error: `automatically_derived` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1 | @@ -166,6 +151,21 @@ LL - #![repr()] LL + #[repr()] | +error: `path` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 + | +LL | #![path = "3800"] + | ^^^^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module + | +help: perhaps you meant to use an outer attribute + | +LL - #![path = "3800"] +LL + #[path = "3800"] + | + error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17 | diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr index b4d2229d408..b6c6e74f260 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/auto-trait-selection-freeze.rs:19:16 | LL | if false { is_trait(foo()) } else { Default::default() } - | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` + | ^^^^^^^^ ----- type must be known at this point + | | + | cannot infer type of the type parameter `U` declared on the function `is_trait` | note: multiple `impl`s satisfying `impl Sized: Trait<_>` found --> $DIR/auto-trait-selection-freeze.rs:16:1 diff --git a/tests/ui/impl-trait/auto-trait-selection.old.stderr b/tests/ui/impl-trait/auto-trait-selection.old.stderr index 1b5fd95fdf9..8e441001771 100644 --- a/tests/ui/impl-trait/auto-trait-selection.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.old.stderr @@ -2,7 +2,9 @@ error[E0283]: type annotations needed --> $DIR/auto-trait-selection.rs:15:16 | LL | if false { is_trait(foo()) } else { Default::default() } - | ^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `is_trait` + | ^^^^^^^^ ----- type must be known at this point + | | + | cannot infer type of the type parameter `U` declared on the function `is_trait` | note: multiple `impl`s satisfying `impl Sized: Trait<_>` found --> $DIR/auto-trait-selection.rs:12:1 diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs new file mode 100644 index 00000000000..e3dc22c1992 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.rs @@ -0,0 +1,46 @@ +// issue#143560 + +trait T { + type Target; +} + +trait Foo { + fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + fn foo() -> impl Sized; + //~^ ERROR: the name `foo` is defined multiple times +} + +trait Bar { + fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + //~^ ERROR: the name `foo` is defined multiple times +} + +struct S<T> { + a: T +} + +trait Baz { + fn foo() -> S<impl T<Target = S<S<impl Sized>>>>; + fn foo() -> S<impl T<Target = S<S<impl Sized>>>>; + //~^ ERROR: the name `foo` is defined multiple times +} + +struct S1<T1, T2> { + a: T1, + b: T2 +} + +trait Qux { + fn foo() -> S1< + impl T<Target = impl T<Target = impl Sized>>, + impl T<Target = impl T<Target = S<impl Sized>>> + >; + fn foo() -> S1< + impl T<Target = impl T<Target = impl Sized>>, + impl T<Target = impl T<Target = S<impl Sized>>> + >; + //~^^^^ ERROR: the name `foo` is defined multiple times +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr new file mode 100644 index 00000000000..f4e73dc1798 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn-with-nested.stderr @@ -0,0 +1,49 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:9:5 + | +LL | fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + | --------------------------------------------------------- previous definition of the value `foo` here +LL | fn foo() -> impl Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:15:5 + | +LL | fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + | --------------------------------------------------------- previous definition of the value `foo` here +LL | fn foo() -> impl T<Target = impl T<Target = impl Sized>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:25:5 + | +LL | fn foo() -> S<impl T<Target = S<S<impl Sized>>>>; + | ------------------------------------------------- previous definition of the value `foo` here +LL | fn foo() -> S<impl T<Target = S<S<impl Sized>>>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn-with-nested.rs:39:5 + | +LL | / fn foo() -> S1< +LL | | impl T<Target = impl T<Target = impl Sized>>, +LL | | impl T<Target = impl T<Target = S<impl Sized>>> +LL | | >; + | |__________- previous definition of the value `foo` here +LL | / fn foo() -> S1< +LL | | impl T<Target = impl T<Target = impl Sized>>, +LL | | impl T<Target = impl T<Target = S<impl Sized>>> +LL | | >; + | |__________^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs index 4fddd7c4ac8..6db0c88f6c0 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs +++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.rs @@ -27,4 +27,15 @@ impl T for () { } } +trait Baz { + fn foo(); + fn foo() -> impl Sized; //~ ERROR: the name `foo` is defined multiple times +} + +trait Foo { + fn foo() -> impl Sized; + fn foo(); //~ ERROR: the name `foo` is defined multiple times + fn foo() -> impl Sized; //~ ERROR: the name `foo` is defined multiple times +} + fn main() {} diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr index b58e8136479..faa65f45d33 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr @@ -8,6 +8,37 @@ LL | fn method() -> impl Sized; | = note: `method` must be defined only once in the value namespace of this trait +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn.rs:32:5 + | +LL | fn foo(); + | --------- previous definition of the value `foo` here +LL | fn foo() -> impl Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn.rs:37:5 + | +LL | fn foo() -> impl Sized; + | ----------------------- previous definition of the value `foo` here +LL | fn foo(); + | ^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/rpitit-duplicate-associated-fn.rs:38:5 + | +LL | fn foo() -> impl Sized; + | ----------------------- previous definition of the value `foo` here +LL | fn foo(); +LL | fn foo() -> impl Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this trait + error[E0201]: duplicate definitions with name `method`: --> $DIR/rpitit-duplicate-associated-fn.rs:12:5 | @@ -47,7 +78,7 @@ LL | fn method() -> impl Sized; LL | impl Bar for () { | ^^^^^^^^^^^^^^^ missing `method` in implementation -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0046, E0201, E0428. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/inline-const/in-pat-recovery.rs b/tests/ui/inline-const/in-pat-recovery.rs index e9e60116ff4..a46e56e3be6 100644 --- a/tests/ui/inline-const/in-pat-recovery.rs +++ b/tests/ui/inline-const/in-pat-recovery.rs @@ -4,7 +4,7 @@ fn main() { match 1 { const { 1 + 7 } => {} - //~^ ERROR `inline_const_pat` has been removed + //~^ ERROR const blocks cannot be used as patterns 2 => {} _ => {} } diff --git a/tests/ui/inline-const/in-pat-recovery.stderr b/tests/ui/inline-const/in-pat-recovery.stderr index e1f2e681e77..0698cff1480 100644 --- a/tests/ui/inline-const/in-pat-recovery.stderr +++ b/tests/ui/inline-const/in-pat-recovery.stderr @@ -1,10 +1,10 @@ -error: `inline_const_pat` has been removed +error: const blocks cannot be used as patterns --> $DIR/in-pat-recovery.rs:6:15 | LL | const { 1 + 7 } => {} | ^^^^^^^^^ | - = help: use a named `const`-item or an `if`-guard instead + = help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr index e07f88b806c..a47a90c90ce 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/issues/issue-7364.stderr @@ -1,8 +1,8 @@ error[E0277]: `RefCell<isize>` cannot be shared between threads safely - --> $DIR/issue-7364.rs:4:1 + --> $DIR/issue-7364.rs:4:15 | LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `RefCell<isize>` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index 275eb056305..2310c12c80b 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -28,19 +28,6 @@ LL | #[macro_use] | ^^^^^^^^^^^^ error: unused attribute - --> $DIR/unused-attr-duplicate.rs:47:1 - | -LL | #[path = "bar.rs"] - | ^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:46:1 - | -LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -error: unused attribute --> $DIR/unused-attr-duplicate.rs:55:1 | LL | #[should_panic(expected = "values don't match")] @@ -154,6 +141,19 @@ LL | #[macro_export] | ^^^^^^^^^^^^^^^ error: unused attribute + --> $DIR/unused-attr-duplicate.rs:47:1 + | +LL | #[path = "bar.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:46:1 + | +LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute --> $DIR/unused-attr-duplicate.rs:53:1 | LL | #[ignore = "some text"] diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr index e3ca90d9acd..4698e381425 100644 --- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr +++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr @@ -10,17 +10,17 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: `#[path]` only has an effect on modules - --> $DIR/unused-attr-macro-rules.rs:8:1 - | -LL | #[path="foo"] - | ^^^^^^^^^^^^^ - error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` --> $DIR/unused-attr-macro-rules.rs:9:1 | LL | #[recursion_limit="1"] | ^^^^^^^^^^^^^^^^^^^^^^ +error: `#[path]` only has an effect on modules + --> $DIR/unused-attr-macro-rules.rs:8:1 + | +LL | #[path="foo"] + | ^^^^^^^^^^^^^ + error: aborting due to 3 previous errors diff --git a/tests/ui/loop-match/panic-in-const.rs b/tests/ui/loop-match/panic-in-const.rs new file mode 100644 index 00000000000..2ae67445496 --- /dev/null +++ b/tests/ui/loop-match/panic-in-const.rs @@ -0,0 +1,22 @@ +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +const CONST_THAT_PANICS: u8 = panic!("diverge!"); +//~^ ERROR: evaluation panicked: diverge! + +fn test(mut state: u8) { + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk CONST_THAT_PANICS; + } + + _ => unreachable!(), + } + } + } +} diff --git a/tests/ui/loop-match/panic-in-const.stderr b/tests/ui/loop-match/panic-in-const.stderr new file mode 100644 index 00000000000..b6ed3177883 --- /dev/null +++ b/tests/ui/loop-match/panic-in-const.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: diverge! + --> $DIR/panic-in-const.rs:5:31 + | +LL | const CONST_THAT_PANICS: u8 = panic!("diverge!"); + | ^^^^^^^^^^^^^^^^^^ evaluation of `CONST_THAT_PANICS` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs index b4815c9dfbb..f4be54da8fe 100644 --- a/tests/ui/process/core-run-destroy.rs +++ b/tests/ui/process/core-run-destroy.rs @@ -37,7 +37,7 @@ pub fn sleeper() -> Child { pub fn sleeper() -> Child { // There's a `timeout` command on windows, but it doesn't like having // its output piped, so instead just ping ourselves a few times with - // gaps in between so we're sure this process is alive for awhile + // gaps in between so we're sure this process is alive for a while t!(Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn()) } diff --git a/tests/ui/resolve/path-attr-in-const-block.rs b/tests/ui/resolve/path-attr-in-const-block.rs index 076511d26d6..69be65bda3f 100644 --- a/tests/ui/resolve/path-attr-in-const-block.rs +++ b/tests/ui/resolve/path-attr-in-const-block.rs @@ -5,5 +5,6 @@ fn main() { const { #![path = foo!()] //~^ ERROR: cannot find macro `foo` in this scope + //~| ERROR malformed `path` attribute input } } diff --git a/tests/ui/resolve/path-attr-in-const-block.stderr b/tests/ui/resolve/path-attr-in-const-block.stderr index 8f9e58157c8..0b5942a287d 100644 --- a/tests/ui/resolve/path-attr-in-const-block.stderr +++ b/tests/ui/resolve/path-attr-in-const-block.stderr @@ -4,5 +4,15 @@ error: cannot find macro `foo` in this scope LL | #![path = foo!()] | ^^^ -error: aborting due to 1 previous error +error[E0539]: malformed `path` attribute input + --> $DIR/path-attr-in-const-block.rs:6:9 + | +LL | #![path = foo!()] + | ^^^^^^^^^^------^ + | | | + | | expected a string literal here + | help: must be of the form: `#[path = "file"]` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/stable-mir-print/async-closure.rs b/tests/ui/stable-mir-print/async-closure.rs index 7da532a359f..80f96e09cfc 100644 --- a/tests/ui/stable-mir-print/async-closure.rs +++ b/tests/ui/stable-mir-print/async-closure.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort +//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort -Zmir-opt-level=0 //@ check-pass //@ only-x86_64 //@ edition: 2024 diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout index 12e7a5530ac..31811299722 100644 --- a/tests/ui/stable-mir-print/async-closure.stdout +++ b/tests/ui/stable-mir-print/async-closure.stdout @@ -8,19 +8,30 @@ fn foo() -> () { debug y => _1; debug x => _2; bb0: { + StorageLive(_1); _1 = 0_i32; + StorageLive(_2); + StorageLive(_3); _3 = &_1; _2 = {coroutine-closure@$DIR/async-closure.rs:9:13: 9:21}(move _3); + StorageDead(_3); + _0 = (); + StorageDead(_2); + StorageDead(_1); return; } } fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {async closure body@$DIR/async-closure.rs:9:22: 11:6} { let mut _0: {async closure body@$DIR/async-closure.rs:9:22: 11:6}; let mut _2: &i32; + let mut _3: &i32; debug y => (*((*_1).0: &i32)); bb0: { - _2 = CopyForDeref(((*_1).0: &i32)); - _0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(_2); + StorageLive(_2); + _3 = CopyForDeref(((*_1).0: &i32)); + _2 = &(*_3); + _0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(move _2); + StorageDead(_2); return; } } @@ -28,25 +39,31 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo let mut _0: Poll<()>; let _3: i32; let mut _4: &i32; - let mut _5: u32; - let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _5: (); + let mut _6: &mut Context<'_>; + let mut _7: u32; let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - debug _task_context => _2; + let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _10: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + debug _task_context => _6; debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); debug y => _3; bb0: { - _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - _5 = discriminant((*_6)); - switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; + _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _7 = discriminant((*_8)); + switchInt(move _7) -> [0: bb1, 1: bb2, otherwise: bb3]; } bb1: { - _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - _4 = CopyForDeref(((*_7).0: &i32)); + _6 = move _2; + StorageLive(_3); + _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _4 = CopyForDeref(((*_9).0: &i32)); _3 = (*_4); - _0 = std::task::Poll::Ready(()); - _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - discriminant((*_8) = 1; + _5 = (); + StorageDead(_3); + _0 = std::task::Poll::Ready(move _5); + _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + discriminant((*_10) = 1; return; } bb2: { @@ -60,25 +77,31 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c let mut _0: Poll<()>; let _3: i32; let mut _4: &i32; - let mut _5: u32; - let mut _6: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _5: (); + let mut _6: &mut Context<'_>; + let mut _7: u32; let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - debug _task_context => _2; + let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + let mut _10: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; + debug _task_context => _6; debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); debug y => _3; bb0: { - _6 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - _5 = discriminant((*_6)); - switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb3]; + _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _7 = discriminant((*_8)); + switchInt(move _7) -> [0: bb1, 1: bb2, otherwise: bb3]; } bb1: { - _7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - _4 = CopyForDeref(((*_7).0: &i32)); + _6 = move _2; + StorageLive(_3); + _9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + _4 = CopyForDeref(((*_9).0: &i32)); _3 = (*_4); - _0 = std::task::Poll::Ready(()); - _8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); - discriminant((*_8) = 1; + _5 = (); + StorageDead(_3); + _0 = std::task::Poll::Ready(move _5); + _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})); + discriminant((*_10) = 1; return; } bb2: { diff --git a/tests/ui/stable-mir-print/basic_function.rs b/tests/ui/stable-mir-print/basic_function.rs index 5f582ece6fb..21469c61f72 100644 --- a/tests/ui/stable-mir-print/basic_function.rs +++ b/tests/ui/stable-mir-print/basic_function.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unpretty=stable-mir -Z mir-opt-level=3 +//@ compile-flags: -Z unpretty=stable-mir -Zmir-opt-level=0 //@ check-pass //@ only-x86_64 //@ needs-unwind unwind edges are different with panic=abort diff --git a/tests/ui/stable-mir-print/basic_function.stdout b/tests/ui/stable-mir-print/basic_function.stdout index 76288c2aa49..319d9c1dc69 100644 --- a/tests/ui/stable-mir-print/basic_function.stdout +++ b/tests/ui/stable-mir-print/basic_function.stdout @@ -2,14 +2,18 @@ // If you find a bug or want to improve the output open a issue at https://github.com/rust-lang/project-stable-mir. fn foo(_1: i32) -> i32 { let mut _0: i32; - let mut _2: (i32, bool); + let mut _2: i32; + let mut _3: (i32, bool); debug i => _1; bb0: { - _2 = CheckedAdd(_1, 1_i32); - assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, 1_i32) -> [success: bb1, unwind continue]; + StorageLive(_2); + _2 = _1; + _3 = CheckedAdd(_2, 1_i32); + assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, 1_i32) -> [success: bb1, unwind continue]; } bb1: { - _0 = move (_2.0: i32); + _0 = move (_3.0: i32); + StorageDead(_2); return; } } @@ -22,15 +26,23 @@ fn bar(_1: &mut Vec<i32>) -> Vec<i32> { debug vec => _1; debug new_vec => _2; bb0: { + StorageLive(_2); + StorageLive(_3); _3 = &(*_1); _2 = <Vec<i32> as Clone>::clone(move _3) -> [return: bb1, unwind continue]; } bb1: { + StorageDead(_3); + StorageLive(_4); + StorageLive(_5); _5 = &mut _2; _4 = Vec::<i32>::push(move _5, 1_i32) -> [return: bb2, unwind: bb3]; } bb2: { + StorageDead(_5); + StorageDead(_4); _0 = move _2; + StorageDead(_2); return; } bb3: { @@ -69,6 +81,7 @@ fn demux(_1: u8) -> u8 { fn main() -> () { let mut _0: (); bb0: { + _0 = (); return; } } diff --git a/tests/ui/stable-mir-print/operands.rs b/tests/ui/stable-mir-print/operands.rs index 34a74e2287e..484ad07cf04 100644 --- a/tests/ui/stable-mir-print/operands.rs +++ b/tests/ui/stable-mir-print/operands.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort +//@ compile-flags: -Z unpretty=stable-mir --crate-type lib -C panic=abort -Zmir-opt-level=0 //@ check-pass //@ only-x86_64 //@ needs-unwind unwind edges are different with panic=abort diff --git a/tests/ui/stable-mir-print/operands.stdout b/tests/ui/stable-mir-print/operands.stdout index c3b1151ae24..37c5ec1a95e 100644 --- a/tests/ui/stable-mir-print/operands.stdout +++ b/tests/ui/stable-mir-print/operands.stdout @@ -3,185 +3,398 @@ fn operands(_1: u8) -> () { let mut _0: (); let _2: [u8; 10]; - let _3: u8; - let _4: usize; - let mut _5: bool; - let _6: u8; - let _7: usize; - let mut _8: (usize, bool); - let mut _9: bool; - let mut _10: (&u8, &u8); - let mut _11: &u8; - let mut _12: &u8; - let _13: &u8; - let _14: &u8; - let mut _15: bool; - let mut _16: u8; - let mut _17: u8; - let _18: core::panicking::AssertKind; - let _19: !; - let mut _20: Option<Arguments<'_>>; - let _21: &u8; - let _22: u8; - let mut _23: (&u8, &u8); + let mut _3: u8; + let _4: u8; + let _5: usize; + let mut _6: bool; + let _7: u8; + let _8: usize; + let mut _9: (usize, bool); + let mut _10: bool; + let _11: (); + let mut _12: (&u8, &u8); + let mut _13: &u8; + let mut _14: &u8; + let _15: &u8; + let _16: &u8; + let mut _17: bool; + let mut _18: u8; + let mut _19: u8; + let mut _20: !; + let _21: core::panicking::AssertKind; + let _22: !; + let mut _23: core::panicking::AssertKind; let mut _24: &u8; - let mut _25: &u8; - let _26: &u8; + let _25: &u8; + let mut _26: &u8; let _27: &u8; - let mut _28: bool; - let mut _29: u8; - let mut _30: u8; - let _31: core::panicking::AssertKind; - let _32: !; - let mut _33: Option<Arguments<'_>>; - let _34: (u8, u8); - let _35: u8; - let _36: u8; - let mut _37: (&u8, &u8); - let mut _38: &u8; - let mut _39: &u8; - let _40: &u8; - let _41: &u8; - let mut _42: bool; - let mut _43: u8; - let mut _44: u8; - let _45: core::panicking::AssertKind; - let _46: !; - let mut _47: Option<Arguments<'_>>; - let _48: usize; - let mut _49: &[u8]; - let mut _50: &[u8; 10]; - let _51: usize; - let _52: &usize; - let mut _53: (&usize, &usize); - let mut _54: &usize; - let mut _55: &usize; - let _56: &usize; - let _57: &usize; - let mut _58: bool; - let mut _59: usize; - let mut _60: usize; - let _61: core::panicking::AssertKind; - let _62: !; - let mut _63: Option<Arguments<'_>>; + let mut _28: Option<Arguments<'_>>; + let _29: &u8; + let _30: u8; + let _31: (); + let mut _32: (&u8, &u8); + let mut _33: &u8; + let mut _34: &u8; + let _35: &u8; + let _36: &u8; + let mut _37: bool; + let mut _38: u8; + let mut _39: u8; + let mut _40: !; + let _41: core::panicking::AssertKind; + let _42: !; + let mut _43: core::panicking::AssertKind; + let mut _44: &u8; + let _45: &u8; + let mut _46: &u8; + let _47: &u8; + let mut _48: Option<Arguments<'_>>; + let _49: (u8, u8); + let mut _50: u8; + let mut _51: u8; + let _52: u8; + let _53: u8; + let _54: (); + let mut _55: (&u8, &u8); + let mut _56: &u8; + let mut _57: &u8; + let _58: &u8; + let _59: &u8; + let mut _60: bool; + let mut _61: u8; + let mut _62: u8; + let mut _63: !; + let _64: core::panicking::AssertKind; + let _65: !; + let mut _66: core::panicking::AssertKind; + let mut _67: &u8; + let _68: &u8; + let mut _69: &u8; + let _70: &u8; + let mut _71: Option<Arguments<'_>>; + let _72: usize; + let mut _73: &[u8]; + let mut _74: &[u8; 10]; + let _75: usize; + let mut _76: &usize; + let _77: &usize; + let _78: (); + let mut _79: (&usize, &usize); + let mut _80: &usize; + let mut _81: &usize; + let _82: &usize; + let _83: &usize; + let mut _84: bool; + let mut _85: usize; + let mut _86: usize; + let mut _87: !; + let _88: core::panicking::AssertKind; + let _89: !; + let mut _90: core::panicking::AssertKind; + let mut _91: &usize; + let _92: &usize; + let mut _93: &usize; + let _94: &usize; + let mut _95: Option<Arguments<'_>>; debug val => _1; debug array => _2; - debug first => _3; - debug last => _6; - debug left_val => _13; - debug right_val => _14; - debug kind => _18; - debug reference => _21; - debug dereferenced => _22; - debug left_val => _26; - debug right_val => _27; - debug kind => _31; - debug tuple => _34; - debug first_again => _35; - debug first_again_again => _36; - debug left_val => _40; - debug right_val => _41; - debug kind => _45; - debug length => _48; - debug size_of => _51; - debug left_val => _56; - debug right_val => _57; - debug kind => _61; + debug first => _4; + debug last => _7; + debug left_val => _15; + debug right_val => _16; + debug kind => _21; + debug reference => _29; + debug dereferenced => _30; + debug left_val => _35; + debug right_val => _36; + debug kind => _41; + debug tuple => _49; + debug first_again => _52; + debug first_again_again => _53; + debug left_val => _58; + debug right_val => _59; + debug kind => _64; + debug length => _72; + debug size_of => _75; + debug left_val => _82; + debug right_val => _83; + debug kind => _88; bb0: { - _2 = [_1; 10]; - _4 = 0_usize; - _5 = Lt(_4, 10_usize); - assert(move _5, "index out of bounds: the length is {} but the index is {}", 10_usize, _4) -> [success: bb1, unwind unreachable]; + StorageLive(_2); + StorageLive(_3); + _3 = _1; + _2 = [move _3; 10]; + StorageDead(_3); + StorageLive(_4); + StorageLive(_5); + _5 = 0_usize; + _6 = Lt(_5, 10_usize); + assert(move _6, "index out of bounds: the length is {} but the index is {}", 10_usize, _5) -> [success: bb1, unwind unreachable]; } bb1: { - _3 = _2[_4]; - _8 = CheckedSub(10_usize, 1_usize); - assert(!move (_8.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; + _4 = _2[_5]; + StorageDead(_5); + StorageLive(_7); + StorageLive(_8); + _9 = CheckedSub(10_usize, 1_usize); + assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", 10_usize, 1_usize) -> [success: bb2, unwind unreachable]; } bb2: { - _7 = move (_8.0: usize); - _9 = Lt(_7, 10_usize); - assert(move _9, "index out of bounds: the length is {} but the index is {}", 10_usize, _7) -> [success: bb3, unwind unreachable]; + _8 = move (_9.0: usize); + _10 = Lt(_8, 10_usize); + assert(move _10, "index out of bounds: the length is {} but the index is {}", 10_usize, _8) -> [success: bb3, unwind unreachable]; } bb3: { - _6 = _2[_7]; - _11 = &_3; - _12 = &_6; - _10 = (move _11, move _12); - _13 = (_10.0: &u8); - _14 = (_10.1: &u8); - _16 = (*_13); - _17 = (*_14); - _15 = Eq(move _16, move _17); - switchInt(move _15) -> [0: bb5, otherwise: bb4]; + _7 = _2[_8]; + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); + _13 = &_4; + StorageLive(_14); + _14 = &_7; + _12 = (move _13, move _14); + StorageDead(_14); + StorageDead(_13); + StorageLive(_15); + _15 = (_12.0: &u8); + StorageLive(_16); + _16 = (_12.1: &u8); + StorageLive(_17); + StorageLive(_18); + _18 = (*_15); + StorageLive(_19); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb5, otherwise: bb4]; } bb4: { - _21 = &_3; - _22 = (*_21); - _24 = &_22; - _25 = &_3; - _23 = (move _24, move _25); - _26 = (_23.0: &u8); - _27 = (_23.1: &u8); - _29 = (*_26); - _30 = (*_27); - _28 = Eq(move _29, move _30); - switchInt(move _28) -> [0: bb7, otherwise: bb6]; + StorageDead(_19); + StorageDead(_18); + _11 = (); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_12); + StorageDead(_11); + StorageLive(_29); + _29 = &_4; + StorageLive(_30); + _30 = (*_29); + StorageLive(_31); + StorageLive(_32); + StorageLive(_33); + _33 = &_30; + StorageLive(_34); + _34 = &_4; + _32 = (move _33, move _34); + StorageDead(_34); + StorageDead(_33); + StorageLive(_35); + _35 = (_32.0: &u8); + StorageLive(_36); + _36 = (_32.1: &u8); + StorageLive(_37); + StorageLive(_38); + _38 = (*_35); + StorageLive(_39); + _39 = (*_36); + _37 = Eq(move _38, move _39); + switchInt(move _37) -> [0: bb7, otherwise: bb6]; } bb5: { - _18 = core::panicking::AssertKind::Eq; - _20 = std::option::Option::None; - _19 = core::panicking::assert_failed::<u8, u8>(move _18, _13, _14, move _20) -> unwind unreachable; + StorageDead(_19); + StorageDead(_18); + StorageLive(_21); + _21 = core::panicking::AssertKind::Eq; + StorageLive(_22); + StorageLive(_23); + _23 = move _21; + StorageLive(_24); + StorageLive(_25); + _25 = &(*_15); + _24 = &(*_25); + StorageLive(_26); + StorageLive(_27); + _27 = &(*_16); + _26 = &(*_27); + StorageLive(_28); + _28 = std::option::Option::None; + _22 = core::panicking::assert_failed::<u8, u8>(move _23, move _24, move _26, move _28) -> unwind unreachable; } bb6: { - _34 = (_3, _6); - _35 = (_34.0: u8); - _36 = (_34.0: u8); - _38 = &_35; - _39 = &_36; - _37 = (move _38, move _39); - _40 = (_37.0: &u8); - _41 = (_37.1: &u8); - _43 = (*_40); - _44 = (*_41); - _42 = Eq(move _43, move _44); - switchInt(move _42) -> [0: bb9, otherwise: bb8]; + StorageDead(_39); + StorageDead(_38); + _31 = (); + StorageDead(_37); + StorageDead(_36); + StorageDead(_35); + StorageDead(_32); + StorageDead(_31); + StorageLive(_49); + StorageLive(_50); + _50 = _4; + StorageLive(_51); + _51 = _7; + _49 = (move _50, move _51); + StorageDead(_51); + StorageDead(_50); + StorageLive(_52); + _52 = (_49.0: u8); + StorageLive(_53); + _53 = (_49.0: u8); + StorageLive(_54); + StorageLive(_55); + StorageLive(_56); + _56 = &_52; + StorageLive(_57); + _57 = &_53; + _55 = (move _56, move _57); + StorageDead(_57); + StorageDead(_56); + StorageLive(_58); + _58 = (_55.0: &u8); + StorageLive(_59); + _59 = (_55.1: &u8); + StorageLive(_60); + StorageLive(_61); + _61 = (*_58); + StorageLive(_62); + _62 = (*_59); + _60 = Eq(move _61, move _62); + switchInt(move _60) -> [0: bb9, otherwise: bb8]; } bb7: { - _31 = core::panicking::AssertKind::Eq; - _33 = std::option::Option::None; - _32 = core::panicking::assert_failed::<u8, u8>(move _31, _26, _27, move _33) -> unwind unreachable; + StorageDead(_39); + StorageDead(_38); + StorageLive(_41); + _41 = core::panicking::AssertKind::Eq; + StorageLive(_42); + StorageLive(_43); + _43 = move _41; + StorageLive(_44); + StorageLive(_45); + _45 = &(*_35); + _44 = &(*_45); + StorageLive(_46); + StorageLive(_47); + _47 = &(*_36); + _46 = &(*_47); + StorageLive(_48); + _48 = std::option::Option::None; + _42 = core::panicking::assert_failed::<u8, u8>(move _43, move _44, move _46, move _48) -> unwind unreachable; } bb8: { - _50 = &_2; - _49 = move _50 as &[u8]; - _48 = PtrMetadata(move _49); - _52 = &_48; - _51 = std::mem::size_of_val::<usize>(_52) -> [return: bb10, unwind unreachable]; + StorageDead(_62); + StorageDead(_61); + _54 = (); + StorageDead(_60); + StorageDead(_59); + StorageDead(_58); + StorageDead(_55); + StorageDead(_54); + StorageLive(_72); + StorageLive(_73); + StorageLive(_74); + _74 = &_2; + _73 = move _74 as &[u8]; + StorageDead(_74); + _72 = core::slice::<impl [u8]>::len(move _73) -> [return: bb10, unwind unreachable]; } bb9: { - _45 = core::panicking::AssertKind::Eq; - _47 = std::option::Option::None; - _46 = core::panicking::assert_failed::<u8, u8>(move _45, _40, _41, move _47) -> unwind unreachable; + StorageDead(_62); + StorageDead(_61); + StorageLive(_64); + _64 = core::panicking::AssertKind::Eq; + StorageLive(_65); + StorageLive(_66); + _66 = move _64; + StorageLive(_67); + StorageLive(_68); + _68 = &(*_58); + _67 = &(*_68); + StorageLive(_69); + StorageLive(_70); + _70 = &(*_59); + _69 = &(*_70); + StorageLive(_71); + _71 = std::option::Option::None; + _65 = core::panicking::assert_failed::<u8, u8>(move _66, move _67, move _69, move _71) -> unwind unreachable; } bb10: { - _54 = &_48; - _55 = &_51; - _53 = (move _54, move _55); - _56 = (_53.0: &usize); - _57 = (_53.1: &usize); - _59 = (*_56); - _60 = (*_57); - _58 = Eq(move _59, move _60); - switchInt(move _58) -> [0: bb12, otherwise: bb11]; + StorageDead(_73); + StorageLive(_75); + StorageLive(_76); + StorageLive(_77); + _77 = &_72; + _76 = &(*_77); + _75 = std::mem::size_of_val::<usize>(move _76) -> [return: bb11, unwind unreachable]; } bb11: { - return; + StorageDead(_76); + StorageDead(_77); + StorageLive(_78); + StorageLive(_79); + StorageLive(_80); + _80 = &_72; + StorageLive(_81); + _81 = &_75; + _79 = (move _80, move _81); + StorageDead(_81); + StorageDead(_80); + StorageLive(_82); + _82 = (_79.0: &usize); + StorageLive(_83); + _83 = (_79.1: &usize); + StorageLive(_84); + StorageLive(_85); + _85 = (*_82); + StorageLive(_86); + _86 = (*_83); + _84 = Eq(move _85, move _86); + switchInt(move _84) -> [0: bb13, otherwise: bb12]; } bb12: { - _61 = core::panicking::AssertKind::Eq; - _63 = std::option::Option::None; - _62 = core::panicking::assert_failed::<usize, usize>(move _61, _56, _57, move _63) -> unwind unreachable; + StorageDead(_86); + StorageDead(_85); + _78 = (); + StorageDead(_84); + StorageDead(_83); + StorageDead(_82); + StorageDead(_79); + StorageDead(_78); + _0 = (); + StorageDead(_75); + StorageDead(_72); + StorageDead(_53); + StorageDead(_52); + StorageDead(_49); + StorageDead(_30); + StorageDead(_29); + StorageDead(_7); + StorageDead(_4); + StorageDead(_2); + return; + } + bb13: { + StorageDead(_86); + StorageDead(_85); + StorageLive(_88); + _88 = core::panicking::AssertKind::Eq; + StorageLive(_89); + StorageLive(_90); + _90 = move _88; + StorageLive(_91); + StorageLive(_92); + _92 = &(*_82); + _91 = &(*_92); + StorageLive(_93); + StorageLive(_94); + _94 = &(*_83); + _93 = &(*_94); + StorageLive(_95); + _95 = std::option::Option::None; + _89 = core::panicking::assert_failed::<usize, usize>(move _90, move _91, move _93, move _95) -> unwind unreachable; } } fn operands::{constant#0}() -> usize { @@ -196,17 +409,41 @@ fn more_operands() -> [Ctors; 3] { let _1: Dummy; let _2: Ctors; let _3: Ctors; - let _4: Ctors; + let mut _4: Dummy; + let _5: Ctors; + let mut _6: Ctors; + let mut _7: Ctors; + let mut _8: Ctors; debug dummy => _1; debug unit => _2; debug struct_like => _3; - debug tup_like => _4; + debug tup_like => _5; bb0: { + StorageLive(_1); _1 = Dummy('a', core::num::<impl i32>::MIN); + StorageLive(_2); _2 = Ctors::Unit; - _3 = Ctors::StructLike(move _1); - _4 = Ctors::TupLike(false); - _0 = [move _2, move _3, move _4]; + StorageLive(_3); + StorageLive(_4); + _4 = move _1; + _3 = Ctors::StructLike(move _4); + StorageDead(_4); + StorageLive(_5); + _5 = Ctors::TupLike(false); + StorageLive(_6); + _6 = move _2; + StorageLive(_7); + _7 = move _3; + StorageLive(_8); + _8 = move _5; + _0 = [move _6, move _7, move _8]; + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); return; } } @@ -230,23 +467,33 @@ fn closures::{closure#0}(_1: {closure@$DIR/operands.rs:47:5: 47:19}, _2: bool) - let mut _0: bool; let mut _3: bool; let mut _4: bool; + let mut _5: bool; debug y => _2; debug x => (_1.0: bool); debug z => (_1.1: bool); bb0: { + StorageLive(_3); + StorageLive(_4); _4 = (_1.0: bool); - _3 = BitXor(move _4, _2); + StorageLive(_5); + _5 = _2; + _3 = BitXor(move _4, move _5); switchInt(move _3) -> [0: bb2, otherwise: bb1]; } bb1: { + StorageDead(_5); + StorageDead(_4); _0 = true; goto -> bb3; } bb2: { + StorageDead(_5); + StorageDead(_4); _0 = (_1.1: bool); goto -> bb3; } bb3: { + StorageDead(_3); return; } } diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr index 6e35db7cc4a..ed195634f12 100644 --- a/tests/ui/static/issue-24446.stderr +++ b/tests/ui/static/issue-24446.stderr @@ -1,8 +1,8 @@ error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely - --> $DIR/issue-24446.rs:2:5 + --> $DIR/issue-24446.rs:2:17 | LL | static foo: dyn Fn() -> u32 = || -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)` = note: shared static variables must have a type that implements `Sync` diff --git a/tests/ui/statics/issue-17718-static-sync.stderr b/tests/ui/statics/issue-17718-static-sync.stderr index d49dbd947c5..96f894146c5 100644 --- a/tests/ui/statics/issue-17718-static-sync.stderr +++ b/tests/ui/statics/issue-17718-static-sync.stderr @@ -1,8 +1,8 @@ error[E0277]: `Foo` cannot be shared between threads safely - --> $DIR/issue-17718-static-sync.rs:9:1 + --> $DIR/issue-17718-static-sync.rs:9:13 | LL | static BAR: Foo = Foo; - | ^^^^^^^^^^^^^^^ `Foo` cannot be shared between threads safely + | ^^^ `Foo` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Foo` = note: shared static variables must have a type that implements `Sync` diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index 8a19207c5d7..e401277a020 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -22,10 +22,10 @@ LL | fn bar() -> i32 where Self: Sized; | +++++++++++++++++ error[E0277]: `(dyn Qux + 'static)` cannot be shared between threads safely - --> $DIR/unsizing-wfcheck-issue-127299.rs:12:1 + --> $DIR/unsizing-wfcheck-issue-127299.rs:12:13 | LL | static FOO: &Lint = &Lint { desc: "desc" }; - | ^^^^^^^^^^^^^^^^^ `(dyn Qux + 'static)` cannot be shared between threads safely + | ^^^^^ `(dyn Qux + 'static)` cannot be shared between threads safely | = help: within `&'static Lint`, the trait `Sync` is not implemented for `(dyn Qux + 'static)` = note: required because it appears within the type `&'static (dyn Qux + 'static)` diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed new file mode 100644 index 00000000000..95fd920dec2 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.fixed @@ -0,0 +1,17 @@ +//@ run-rustfix + +struct S; +trait Trait { + fn foo() {} +} +impl Trait for &S {} +impl Trait for &mut S {} +fn main() { + let _ = <&str>::from("value"); + //~^ ERROR the trait bound `str: From<_>` is not satisfied + //~| ERROR the size for values of type `str` cannot be known at compilation time + let _ = <&mut S>::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = <&S>::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs new file mode 100644 index 00000000000..f79d2465062 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.rs @@ -0,0 +1,17 @@ +//@ run-rustfix + +struct S; +trait Trait { + fn foo() {} +} +impl Trait for &S {} +impl Trait for &mut S {} +fn main() { + let _ = &str::from("value"); + //~^ ERROR the trait bound `str: From<_>` is not satisfied + //~| ERROR the size for values of type `str` cannot be known at compilation time + let _ = &mut S::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied + let _ = &S::foo(); + //~^ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr new file mode 100644 index 00000000000..ac96ec76da7 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr @@ -0,0 +1,58 @@ +error[E0277]: the trait bound `str: From<_>` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:10:14 + | +LL | let _ = &str::from("value"); + | ^^^ the trait `From<_>` is not implemented for `str` + | + = help: the following other types implement trait `From<T>`: + `String` implements `From<&String>` + `String` implements `From<&mut str>` + `String` implements `From<&str>` + `String` implements `From<Box<str>>` + `String` implements `From<Cow<'_, str>>` + `String` implements `From<char>` +help: you likely meant to call the associated function `from` for type `&str`, but the code as written calls associated function `from` on type `str` + | +LL | let _ = <&str>::from("value"); + | + + + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:13:18 + | +LL | let _ = &mut S::foo(); + | ^ the trait `Trait` is not implemented for `S` + | + = help: the following other types implement trait `Trait`: + &S + &mut S +help: you likely meant to call the associated function `foo` for type `&mut S`, but the code as written calls associated function `foo` on type `S` + | +LL | let _ = <&mut S>::foo(); + | + + + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:15:14 + | +LL | let _ = &S::foo(); + | ^ the trait `Trait` is not implemented for `S` + | + = help: the following other types implement trait `Trait`: + &S + &mut S +help: you likely meant to call the associated function `foo` for type `&S`, but the code as written calls associated function `foo` on type `S` + | +LL | let _ = <&S>::foo(); + | + + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dont-suggest-borrowing-existing-borrow.rs:10:14 + | +LL | let _ = &str::from("value"); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-bounds/false-span-in-trait-bound-label.rs b/tests/ui/trait-bounds/false-span-in-trait-bound-label.rs new file mode 100644 index 00000000000..0e307309860 --- /dev/null +++ b/tests/ui/trait-bounds/false-span-in-trait-bound-label.rs @@ -0,0 +1,10 @@ +// In this test, the span of the trait bound label should point to `1`, not `""`. +// See issue #143336 + +trait A<T> { + fn f(self, x: T); +} + +fn main() { + A::f(1, ""); //~ ERROR the trait bound `{integer}: A<_>` is not satisfied [E0277] +} diff --git a/tests/ui/trait-bounds/false-span-in-trait-bound-label.stderr b/tests/ui/trait-bounds/false-span-in-trait-bound-label.stderr new file mode 100644 index 00000000000..9a480273338 --- /dev/null +++ b/tests/ui/trait-bounds/false-span-in-trait-bound-label.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `{integer}: A<_>` is not satisfied + --> $DIR/false-span-in-trait-bound-label.rs:9:10 + | +LL | A::f(1, ""); + | ---- ^ the trait `A<_>` is not implemented for `{integer}` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/false-span-in-trait-bound-label.rs:4:1 + | +LL | trait A<T> { + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr index fdf0b1722be..23cced2bc28 100644 --- a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -34,10 +34,10 @@ LL | <dyn CompareToInts>::same_as(c, 22) `i64` implements `CompareTo<u64>` error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied - --> $DIR/repeated-supertrait-ambig.rs:38:27 + --> $DIR/repeated-supertrait-ambig.rs:38:24 | LL | CompareTo::same_as(c, 22) - | ------------------ ^^ the trait `CompareTo<i32>` is not implemented for `C` + | ------------------ ^ the trait `CompareTo<i32>` is not implemented for `C` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr index 17c3db9ad33..12984c7936c 100644 --- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 | LL | test(22, std::default::Default::default()); - | ^^^^ -------------------------------- type must be known at this point + | ^^^^ -- type must be known at this point | | | cannot infer type of the type parameter `U` declared on the function `test` | diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr index ab3378eaa4a..bbe93a05d4d 100644 --- a/tests/ui/type/type-check-defaults.stderr +++ b/tests/ui/type/type-check-defaults.stderr @@ -29,18 +29,36 @@ error[E0277]: the trait bound `String: Copy` is not satisfied | LL | struct Bounds<T:Copy=String>(T); | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `Bounds` + --> $DIR/type-check-defaults.rs:11:17 + | +LL | struct Bounds<T:Copy=String>(T); + | ^^^^ required by this bound in `Bounds` error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:14:42 | LL | struct WhereClause<T=String>(T) where T: Copy; | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `WhereClause` + --> $DIR/type-check-defaults.rs:14:42 + | +LL | struct WhereClause<T=String>(T) where T: Copy; + | ^^^^ required by this bound in `WhereClause` error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/type-check-defaults.rs:17:20 | LL | trait TraitBound<T:Copy=String> {} | ^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `TraitBound` + --> $DIR/type-check-defaults.rs:17:20 + | +LL | trait TraitBound<T:Copy=String> {} + | ^^^^ required by this bound in `TraitBound` error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/type-check-defaults.rs:21:25 @@ -70,6 +88,11 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} `&i32` implements `Add` `i32` implements `Add<&i32>` `i32` implements `Add` +note: required by a bound in `ProjectionPred` + --> $DIR/type-check-defaults.rs:24:66 + | +LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} + | ^^^^^^^ required by this bound in `ProjectionPred` error: aborting due to 7 previous errors |
