diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 2218780092287..521043e3f6c1a 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1132,6 +1132,11 @@ impl LayoutCalculator { // If `-Z randomize-layout` was enabled for the type definition we can shuffle // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee. + // In the future, we might do more than shuffle field order (e.g. introduce extra padding), + // but never for `repr(Rust)` structs with only zero-sized fields, single-variant + // `repr(Rust)` enums with only zero-sized fields, or zero-variant `repr(Rust)` enums, + // which must remain zero-sized as per T-lang decisions in + // https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293 if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { #[cfg(feature = "randomize")] { diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 9ca4aa2254547..c5d8d758c4733 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -284,6 +284,27 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { found } + /// Whether this type/layout has any padding that is dependent on a variant, i.e. has bytes that + /// are padding for some, but not all, valid values of this type. + pub fn has_variant_dependent_padding(&self, cx: &C) -> bool + where + Ty: TyAbiInterface<'a, C> + Copy, + { + match self.variants { + Variants::Multiple { .. } => true, + Variants::Empty => false, + Variants::Single { .. } => match &self.fields { + FieldsShape::Primitive | FieldsShape::Union(_) => false, + FieldsShape::Array { count, .. } => { + *count > 0 && self.field(cx, 0).has_variant_dependent_padding(cx) + } + FieldsShape::Arbitrary { offsets, .. } => { + (0..offsets.len()).any(|i| self.field(cx, i).has_variant_dependent_padding(cx)) + } + }, + } + } + /// The ranges of bytes that are always ignored by the representation relation of this type. /// /// In other words, for any sequence of bytes, if we reset the these padding bytes to uninit, @@ -291,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// This is the "guaranteed" padding. There may be more bytes that are padding for some /// but not all variants of this type; those are not included. /// (E.g. `Option` has no guaranteed padding so the empty range set is returned, but its `None` value still has padding). - pub fn padding_ranges(&self, cx: &C) -> Vec> + pub fn variant_independent_padding_ranges(&self, cx: &C) -> Vec> where Ty: TyAbiInterface<'a, C> + Copy, { @@ -316,6 +337,45 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { uninit_ranges } + /// The ranges of bytes that are ignored by the representation relation of this variant. + /// + /// The result does not include variant-independent padding. + pub fn variant_dependent_padding_ranges( + &self, + cx: &C, + variant_index: VariantIdx, + ) -> Vec> + where + Ty: TyAbiInterface<'a, C> + Copy, + { + let Variants::Multiple { .. } = self.variants else { + return Vec::new(); + }; + + // Bytes that are data in some variant. + let mut any = RangeSet::new(); + self.add_data_ranges(cx, Size::ZERO, &mut any); + + // Bytes that are data in this variant. + let mut this = RangeSet::new(); + + // The variants do not contain e.g. the discriminant or coroutine upvars. + let FieldsShape::Arbitrary { offsets, in_memory_order: _ } = &self.fields else { + unreachable!("a multi-variant layout should have `Arbitrary` fields") + }; + + // So add them explicitly. + for (field, &offset) in offsets.iter_enumerated() { + let field = self.field(cx, field.as_usize()); + field.add_data_ranges(cx, offset, &mut this); + } + + self.for_variant(cx, variant_index).add_data_ranges(cx, Size::ZERO, &mut this); + + // Padding specific to this variant: data in some variant, but not in this one. + any.difference(&this).0.iter().map(|&(offset, size)| offset..offset + size).collect() + } + /// Extend `out` with all ranges of bytes that *may* carry relevant data for values of this type. /// For enums and unions there are offsets that are initialized for some /// variants but not for others; those offset *will* get added to `out`. @@ -327,39 +387,42 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { return; } - match &self.variants { - Variants::Empty => { /* done */ } - Variants::Single { index: _ } => match &self.fields { - FieldsShape::Primitive => { - out.add_range(base_offset, self.size); - } - &FieldsShape::Union(field_count) => { - for field in 0..field_count.get() { - let field = self.field(cx, field); - field.add_data_ranges(cx, base_offset, out); - } + // Visit the fields of this value. For enum values the fields include the discriminant. + match &self.fields { + FieldsShape::Primitive => { + out.add_range(base_offset, self.size); + } + &FieldsShape::Union(field_count) => { + for field in 0..field_count.get() { + let field = self.field(cx, field); + field.add_data_ranges(cx, base_offset, out); } - &FieldsShape::Array { stride, count } => { - let elem = self.field(cx, 0); - - // For scalars we know there is no padding between the elements, - // so the entire array is a single big data range. - if elem.backend_repr.is_scalar() { - out.add_range(base_offset, elem.size * count); - } else { - // FIXME: this is really inefficient for large arrays. - for idx in 0..count { - elem.add_data_ranges(cx, base_offset + idx * stride, out); - } + } + &FieldsShape::Array { stride, count } => { + let elem = self.field(cx, 0); + + // For scalars we know there is no padding between the elements, + // so the entire array is a single big data range. + if elem.backend_repr.is_scalar() { + out.add_range(base_offset, elem.size * count); + } else { + // FIXME: this is really inefficient for large arrays. + for idx in 0..count { + elem.add_data_ranges(cx, base_offset + idx * stride, out); } } - FieldsShape::Arbitrary { offsets, in_memory_order: _ } => { - for (field, &offset) in offsets.iter_enumerated() { - let field = self.field(cx, field.as_usize()); - field.add_data_ranges(cx, base_offset + offset, out); - } + } + FieldsShape::Arbitrary { offsets, in_memory_order: _ } => { + for (field, &offset) in offsets.iter_enumerated() { + let field = self.field(cx, field.as_usize()); + field.add_data_ranges(cx, base_offset + offset, out); } - }, + } + } + + // Visit the fields of each variant. + match &self.variants { + Variants::Empty | Variants::Single { index: _ } => { /* done */ } Variants::Multiple { variants, .. } => { for variant in variants.indices() { let variant = self.for_variant(cx, variant); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index bff4c9bdf47ef..679523341c7e3 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -90,6 +90,10 @@ bitflags! { /// If true, the type's crate has opted into layout randomization. /// Other flags can still inhibit reordering and thus randomization. /// The seed stored in `ReprOptions.field_shuffle_seed`. + /// + /// `repr(Rust)` structs with only zero-sized fields, single-variant `repr(Rust)` enums with only + /// zero-sized fields, and zero-variant `repr(Rust)` enums must remain zero-sized as per + /// T-lang decisions in https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293 const RANDOMIZE_LAYOUT = 1 << 4; /// If true, the type is always passed indirectly by non-Rustic ABIs. /// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 5bdb6a707fd7a..5d9c1a876f0cb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -2,7 +2,8 @@ use std::cmp; use std::ops::Range; use rustc_abi::{ - Align, ArmCall, BackendRepr, CanonAbi, ExternAbi, HasDataLayout, Reg, Size, WrappingRange, + Align, ArmCall, BackendRepr, CanonAbi, ExternAbi, FieldsShape, HasDataLayout, Reg, Size, + VariantIdx, Variants, WrappingRange, }; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; @@ -11,7 +12,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::lang_items::LangItem; use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER; use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason}; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -618,15 +619,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.conv == CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) { // The return value of an `extern "cmse-nonsecure-entry"` function crosses the - // secure boundary. Zero padding bytes so information does not leak. - // - // This only zeroes "guaranteed" padding. There may be more bytes that are - // padding for some but not all variants of this type; those are not zeroed. - // - // Returning a value with value-dependent padding will instead trigger a lint. + // secure boundary. Clear any padding bytes so information does not leak. let ret_layout = self.fn_abi.ret.layout; - let uninit_ranges = ret_layout.padding_ranges(bx.cx()); - self.zero_byte_ranges(bx, llslot, ret_layout.size, &uninit_ranges); + self.clear_padding_cmse(bx, llslot, ret_layout.size, ret_layout); } load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi) @@ -1745,22 +1740,166 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + /// When using CMSE, values that cross the secure boundary from secure to non-secure mode can + /// contain stale secure data in their padding bytes. This function clears that data. This is + /// required when a value is: + /// + /// - passed to an `extern "cmse-nonsecure-call"` function + /// - returned from an `extern "cmse-nonsecure-entry"` function + /// + /// This function clears both: + /// + /// - variant-independent padding, bytes that are padding for all valid values of the type + /// - variant-dependent padding, bytes that are padding for some but not all values of the type + /// + /// Clearing variant-dependent padding requires looking at the data at runtime to determine what + /// bytes to clear. + fn clear_padding_cmse( + &mut self, + bx: &mut Bx, + base_ptr: Bx::Value, + limit: Size, + layout: TyAndLayout<'tcx>, + ) { + // First clear variant-independent padding, a series of memsets. + let variant_independent = layout.variant_independent_padding_ranges(self.cx); + self.zero_byte_ranges(bx, base_ptr, Size::ZERO, limit, &variant_independent); + + // Then clear the extra padding of the active variant of any (nested) enum. + self.clear_variant_dependent_padding(bx, base_ptr, Size::ZERO, limit, layout); + } + + fn clear_variant_dependent_padding( + &mut self, + bx: &mut Bx, + base_ptr: Bx::Value, + base_offset: Size, + limit: Size, + layout: TyAndLayout<'tcx>, + ) { + let cx = self.cx; + + if !layout.has_variant_dependent_padding(cx) { + return; + } + + // Recurse into aggregate fields/elements to reach any nested enums. + match layout.fields { + FieldsShape::Array { stride, count } => { + let elem = layout.field(cx, 0); + if elem.has_variant_dependent_padding(cx) { + for idx in 0..count { + let off = base_offset + idx * stride; + self.clear_variant_dependent_padding(bx, base_ptr, off, limit, elem); + } + } + } + FieldsShape::Arbitrary { .. } => { + for i in 0..layout.fields.count() { + let field = layout.field(cx, i); + if field.has_variant_dependent_padding(cx) { + let off = base_offset + layout.fields.offset(i); + self.clear_variant_dependent_padding(bx, base_ptr, off, limit, field); + } + } + } + FieldsShape::Primitive | FieldsShape::Union(_) => { /* nothing to visit */ } + } + + // If this is not a multi-variant enum, we're done. + let Variants::Multiple { ref variants, .. } = layout.variants else { + return; + }; + + // Collect variants that will need padding cleared. + let mut work = Vec::with_capacity(variants.len()); + for i in 0..variants.len() { + let idx = VariantIdx::from_usize(i); + let variant = layout.for_variant(cx, idx); + + // Don't consider uninhabited variants. + if variant.is_uninhabited() { + continue; + } + + let variant_dependent = layout.variant_dependent_padding_ranges(cx, idx); + let has_nested_variant_dependent = (0..variant.fields.count()) + .any(|i| variant.field(cx, i).has_variant_dependent_padding(cx)); + + if !variant_dependent.is_empty() || has_nested_variant_dependent { + work.push((idx, variant, variant_dependent)); + } + } + + if work.is_empty() { + return; + } + + // Build the switch and clear the appropriate padding for each variant. + let root_block = bx.llbb(); + let join_block = bx.append_sibling_block("cmse_pad_join"); + let mut cases = Vec::with_capacity(work.len()); + + for (idx, variant, variant_dependent) in work.into_iter() { + let Some(discr) = layout.ty.discriminant_for_variant(bx.tcx(), idx) else { + bug!("multi-variant layout on a type without discriminants"); + }; + + let variant_block = bx.append_sibling_block("cmse_pad_variant"); + bx.switch_to_block(variant_block); + + // Clear the padding of this variant. + self.zero_byte_ranges(bx, base_ptr, base_offset, limit, &variant_dependent); + + // Recurse into the fields. + for i in 0..variant.fields.count() { + let field = variant.field(cx, i); + let off = base_offset + variant.fields.offset(i); + self.clear_variant_dependent_padding(bx, base_ptr, off, limit, field); + } + + bx.br(join_block); + cases.push((discr.val, variant_block)); + } + + // Construct the dispatch. + bx.switch_to_block(root_block); + + let discr_ty = layout.ty.discriminant_ty(bx.tcx()); + let enum_ptr = bx.inbounds_ptradd(base_ptr, bx.const_usize(base_offset.bytes())); + let operand = OperandRef { + val: OperandValue::Ref(PlaceValue::new_sized(enum_ptr, layout.align.abi)), + layout, + move_annotation: None, + }; + let discr = operand.codegen_get_discr(self, bx, discr_ty); + + // Default to the join block (for variants without variant-dependent padding). + bx.switch(discr, join_block, cases.into_iter()); + + bx.switch_to_block(join_block); + } + fn zero_byte_ranges( &mut self, bx: &mut Bx, ptr: Bx::Value, + offset: Size, limit: Size, ranges: &[Range], ) { let zero = bx.const_u8(0); for range in ranges { - let end = cmp::min(range.end, limit); + let start = range.start + offset; + let end = range.end + offset; + + let end = cmp::min(end, limit); if range.start >= end { continue; } - let offset = bx.const_usize(range.start.bytes()); - let len = bx.const_usize((end - range.start).bytes()); + let offset = bx.const_usize(start.bytes()); + let len = bx.const_usize((end - start).bytes()); let ptr = bx.inbounds_ptradd(ptr, offset); bx.memset(ptr, zero, len, Align::ONE, MemFlags::empty()); } @@ -1902,18 +2041,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); // The arguments of an `extern "cmse-nonsecure-call"` function cross the secure - // boundary. Zero padding bytes so information does not leak. - // - // This only zeroes "guaranteed" padding. There may be more bytes that are - // padding for some but not all variants of this type; those are not zeroed. - // - // Passing an argument with value-dependent padding will instead trigger a lint. + // boundary. Clear any padding bytes so information does not leak. if conv == CanonAbi::Arm(ArmCall::CCmseNonSecureCall) { - self.zero_byte_ranges( + self.clear_padding_cmse( bx, llscratch, Size::from_bytes(copy_bytes), - &arg.layout.padding_ranges(bx.cx()), + arg.layout, ); } 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 57ccbb8ff10ea..b2c6663e41085 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -44,6 +44,7 @@ fn retry_codegen_mode_with_postanalysis<'tcx, K: TypeVisitable>, V> | ty::TypingMode::Typeck { .. } | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostAnalysis => {} } diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index cbef1de487c43..1b23432c8c57a 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -29,7 +29,10 @@ pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>( ); }; - let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ecx.typing_env); + let (infcx, param_env) = ecx.tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::new( + ecx.typing_env.param_env, + ty::TypingMode::Reflection, + )); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| { diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 5b63379edd332..7fe32b4e75ffb 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -33,6 +33,7 @@ fn assert_typing_mode(typing_mode: ty::TypingMode<'_>) { // `InterpCx::new` for more details. ty::TypingMode::Coherence | ty::TypingMode::Typeck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } => bug!( "Const eval should always happens in PostAnalysis or Codegen mode. See the comment on `assert_typing_mode` for more details." diff --git a/compiler/rustc_data_structures/src/range_set.rs b/compiler/rustc_data_structures/src/range_set.rs index 514946a0fb2de..bd18728e20da5 100644 --- a/compiler/rustc_data_structures/src/range_set.rs +++ b/compiler/rustc_data_structures/src/range_set.rs @@ -56,4 +56,44 @@ where v.insert(idx, (offset, size)); } } + + /// The ranges from `self` with any intersection with `other` removed. + pub fn difference(&self, other: &Self) -> Self { + let (a, b) = (self, other); + let mut out = Vec::new(); + + let mut j = 0; + for &(a_offset, a_size) in a.0.iter() { + let mut cursor = a_offset; + let a_end = a_offset + a_size; + + // Skip ranges of `b` that end before this range of `a` begins. + // both sequences are sorted they cannot overlap any later range of `a` either. + while let Some(&(b_offset, b_size)) = b.0.get(j) + && b_offset + b_size <= cursor + { + j += 1; + } + + // Carve out each range of `b` that overlaps this range of `a`. A range of `b` may extend + // past `a_end` and overlap the next range of `a`, so leave `j` pointing at it. + let mut k = j; + while let Some(&(b_offset, b_size)) = b.0.get(k) + && b_offset < a_end + { + if b_offset > cursor { + out.push((cursor, b_offset)); + } + cursor = Ord::max(cursor, b_offset + b_size); + k += 1; + } + + // Keep the remainder of the `a`'s range. + if cursor < a_end { + out.push((cursor, a_end)); + } + } + + Self(out) + } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 8b897aa3c5f96..48a0cc575fbeb 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1336,8 +1336,6 @@ impl InvocationCollectorNode for Box { return Ok(walk_flat_map(node, collector)); } - // Work around borrow checker not seeing through `P`'s deref. - let (span, mut attrs) = (node.span, mem::take(&mut node.attrs)); let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() }; let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { @@ -1346,7 +1344,7 @@ impl InvocationCollectorNode for Box { let (dir_path, dir_ownership) = mod_dir_path( ecx.sess, ident, - &attrs, + &node.attrs, &ecx.current_expansion.module, ecx.current_expansion.dir_ownership, *inline, @@ -1355,14 +1353,13 @@ impl InvocationCollectorNode for Box { // This lets `parse_external_mod` catch cycles if it's self-referential. let file_path = match inline { Inline::Yes => None, - Inline::No { .. } => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path), + Inline::No { .. } => mod_file_path_from_attr(ecx.sess, &node.attrs, &dir_path), }; - node.attrs = attrs; (file_path, dir_path, dir_ownership) } ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. - let old_attrs_len = attrs.len(); + let old_attrs_len = node.attrs.len(); let ParsedExternalMod { items, spans, @@ -1373,10 +1370,10 @@ impl InvocationCollectorNode for Box { } = parse_external_mod( ecx.sess, ident, - span, + node.span, &ecx.current_expansion.module, ecx.current_expansion.dir_ownership, - &mut attrs, + &mut node.attrs, ); if let Some(lint_store) = ecx.lint_store { @@ -1385,14 +1382,13 @@ impl InvocationCollectorNode for Box { ecx.ecfg.features, ecx.resolver.registered_tools(), ecx.current_expansion.lint_node_id, - &attrs, + &node.attrs, &items, ident.name, ); } *mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans); - node.attrs = attrs; if node.attrs.len() > old_attrs_len { // If we loaded an out-of-line module and added some inner attributes, // then we need to re-configure it and re-collect attributes for diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 1592dfdde4e6f..92f48cda10f9f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -194,6 +194,8 @@ language_item_table! { CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1); DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1); + TryAsDyn, sym::try_as_dyn, try_as_dyn, Target::Trait, GenericRequirement::Exact(1); + // lang items relating to transmutability TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0); TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(2); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b520ea106dfa0..605b6e3751ef3 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -85,6 +85,7 @@ pub(crate) fn provide(providers: &mut Providers) { adt_def, fn_sig, impl_trait_header, + impl_is_fully_generic_for_reflection, coroutine_kind, coroutine_for_closure, opaque_ty_origin, @@ -1395,6 +1396,11 @@ pub fn suggest_impl_trait<'tcx>( None } +fn impl_is_fully_generic_for_reflection(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + tcx.impl_trait_header(def_id).is_fully_generic_for_reflection() + && tcx.explicit_predicates_of(def_id).is_fully_generic_for_reflection() +} + fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir_expect_item(def_id); 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 b59bed76eadd7..f5b4cee8dedf2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2933,7 +2933,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } Res::Def(DefKind::Static { .. }, _) => { - span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") + let guar = self + .dcx() + .span_err(path.span, "static items cannot be used as const arguments"); + return Const::new_error(tcx, guar); } // FIXME(const_generics): create real const to allow fn items as const paths Res::Def(DefKind::Fn | DefKind::AssocFn, did) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9a1b1f8300957..b413d0c0bb2de 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -142,8 +142,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. - // FIXME(-Znext-solver): A lot of the calls to this method should - // probably be `resolve_vars_with_obligations` or `structurally_resolve_type` instead. #[instrument(skip(self), level = "debug", ret)] pub(crate) fn resolve_vars_with_obligations>>( &self, @@ -696,6 +694,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { defining_opaque_types_and_generators } ty::TypingMode::Coherence + | ty::TypingMode::Reflection | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index 797077d97c133..17e193d7f44ab 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -103,6 +103,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { defining_opaque_types_and_generators } ty::TypingMode::Coherence + | ty::TypingMode::Reflection | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index af1f5de717a60..72820a31a95b9 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -354,6 +354,7 @@ impl<'tcx> Drop for InferCtxt<'tcx> { TypingMode::Coherence | TypingMode::Typeck { .. } | TypingMode::PostBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => {} // In erased mode, the opaque type storage is always empty @@ -1171,6 +1172,7 @@ impl<'tcx> InferCtxt<'tcx> { // and post-borrowck analysis mode. We may need to modify its uses // to support PostBorrowck in the old solver as well. TypingMode::Coherence + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen => false, @@ -1505,6 +1507,7 @@ impl<'tcx> InferCtxt<'tcx> { mode @ (ty::TypingMode::Coherence | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis + | ty::TypingMode::Reflection | ty::TypingMode::Codegen) => mode, ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(), }; diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 2d05e33e44891..08c7c49417124 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -285,7 +285,8 @@ impl<'tcx> InferCtxt<'tcx> { } mode @ (ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis - | ty::TypingMode::Codegen) => { + | ty::TypingMode::Codegen + | ty::TypingMode::Reflection) => { bug!("insert hidden type in {mode:?}") } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 2a138154f7020..9acebc1a4822f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -241,6 +241,7 @@ provide! { tcx, def_id, other, cdata, fn_sig => { table } codegen_fn_attrs => { table } impl_trait_header => { table } + impl_is_fully_generic_for_reflection => { table_direct } const_param_default => { table } object_lifetime_default => { table } thir_abstract_const => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8fa0c1b2dcdd8..602c5ee0201dd 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2197,6 +2197,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let header = tcx.impl_trait_header(def_id); record!(self.tables.impl_trait_header[def_id] <- header); + let impl_is_fully_generic_for_reflection = + tcx.impl_is_fully_generic_for_reflection(def_id); + self.tables + .impl_is_fully_generic_for_reflection + .set(def_id.index, impl_is_fully_generic_for_reflection); + self.tables.defaultness.set(def_id.index, tcx.defaultness(def_id)); let trait_ref = header.trait_ref.instantiate_identity().skip_norm_wip(); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 4847ddda90fd1..237672878bb4c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -413,6 +413,7 @@ define_tables! { constness: Table, safety: Table, defaultness: Table, + impl_is_fully_generic_for_reflection: Table, - optional: attributes: Table>, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index cbd54ec959c6a..387bf3f6f8c1f 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1098,6 +1098,15 @@ rustc_queries! { separate_provide_extern } + /// Whether all generic parameters of the type are unique unconstrained generic parameters + /// of the impl. `Bar<'static>` or `Foo<'a, 'a>` or outlives bounds on the lifetimes cause + /// this boolean to be false and `try_as_dyn` to return `None`. + query impl_is_fully_generic_for_reflection(impl_id: DefId) -> bool { + desc { "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } + cache_on_disk + separate_provide_extern + } + /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct /// whose tail is one of those types. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 92f7ed0cb19f6..a2eecebcc3501 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -180,6 +180,8 @@ pub enum SelectionCandidate<'tcx> { BuiltinUnsizeCandidate, BikeshedGuaranteedNoDropCandidate, + + TryAsDynCandidate, } /// The result of trait evaluation. The order is important diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 052a937cf5017..0f5ec3e04ddce 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -703,6 +703,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.impl_polarity(impl_def_id) } + fn is_fully_generic_for_reflection(self, impl_def_id: Self::ImplId) -> bool { + self.impl_is_fully_generic_for_reflection(impl_def_id) + } + fn trait_is_auto(self, trait_def_id: DefId) -> bool { self.trait_is_auto(trait_def_id) } @@ -934,6 +938,7 @@ bidirectional_lang_item_map! { Sized, TransmuteTrait, TrivialClone, + TryAsDyn, Tuple, Unpin, Unsize, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 02ac0586c33ae..9a6b3dbea1ef3 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -1,14 +1,16 @@ +use std::ops::ControlFlow; + use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use rustc_span::{Span, Symbol, kw}; +use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor}; use tracing::instrument; use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized}; -use crate::ty; use crate::ty::region::RegionExt; -use crate::ty::{EarlyBinder, GenericArgsRef}; +use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind}; #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash)] pub enum GenericParamDefKind { @@ -456,6 +458,76 @@ impl<'tcx> GenericPredicates<'tcx> { instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| Unnormalized::new(*p))); instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); } + + /// Allow simple where bounds like `T: Debug`, but prevent any kind of + /// outlives bounds or uses of generic parameters on the right hand side. + /// + /// We allow simple bounds because when the `T` actually gets substituted with a concrete type + /// during monomorphization, we will be checking its `Debug` impl for fully_generic_for_reflection. + /// + /// Constants (associated or generic) are irrelevant for this analysis, as their value is neither + /// affected by lifetimes, nor do they affect lifetimes. + pub fn is_fully_generic_for_reflection(self) -> bool { + struct ParamChecker; + impl<'tcx> TypeVisitor> for ParamChecker { + type Result = ControlFlow<()>; + fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { + match r.kind() { + RegionKind::ReEarlyParam(_) | RegionKind::ReStatic | RegionKind::ReError(_) => { + ControlFlow::Break(()) + } + RegionKind::ReVar(_) + | RegionKind::RePlaceholder(_) + | RegionKind::ReErased + | RegionKind::ReLateParam(_) => { + bug!("unexpected lifetime in impl: {r:?}") + } + RegionKind::ReBound(..) => ControlFlow::Continue(()), + } + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + match t.kind() { + TyKind::Param(_p) => { + // Reject using parameters used in the type in where bounds + return ControlFlow::Break(()); + } + TyKind::Alias(..) => return ControlFlow::Break(()), + _ => (), + } + t.super_visit_with(self) + } + } + + // Pessimistic: if any of the parameters have where bounds + // don't allow this impl to be used. + self.predicates.iter().all(|(clause, _)| { + match clause.kind().skip_binder() { + ClauseKind::Trait(trait_predicate) => { + // In a `T: Trait`, if the rhs bound does not contain any generic params + // or 'static lifetimes, then it cannot transitively cause such requirements, + // considering we apply the fully-generic-for-reflection rules to any impls for + // that trait, too. + if matches!(trait_predicate.self_ty().kind(), ty::Param(_)) + && trait_predicate.trait_ref.args[1..] + .iter() + .all(|arg| arg.visit_with(&mut ParamChecker).is_continue()) + { + return true; + } + } + ClauseKind::RegionOutlives(_) + | ClauseKind::TypeOutlives(_) + | ClauseKind::Projection(_) + | ClauseKind::ConstArgHasType(_, _) + | ClauseKind::WellFormed(_) + | ClauseKind::ConstEvaluatable(_) + | ClauseKind::HostEffect(_) + | ClauseKind::UnstableFeature(_) => {} + } + clause.visit_with(&mut ParamChecker).is_continue() + }) + } } /// `[const]` bounds for a given item. This is represented using a struct much like diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9b582eeb2c520..151ca10b85ef6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -16,6 +16,7 @@ use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::num::NonZero; +use std::ops::ControlFlow; use std::ptr::NonNull; use std::{assert_matches, fmt, iter, str}; @@ -30,7 +31,7 @@ use rustc_abi::{ use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId}; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; use rustc_data_structures::steal::Steal; @@ -309,6 +310,64 @@ pub struct ImplTraitHeader<'tcx> { pub constness: hir::Constness, } +impl<'tcx> ImplTraitHeader<'tcx> { + /// For trait impls, checks whether + /// * the type and trait only use generic lifetime arguments (and no concrete ones like `'static`), and + /// * uses any generic param (lifetime or type) only once. + /// + /// This is a pessimistic analysis, so it will reject alias types + /// and other types that may be actually ok. We can allow more in the future. + /// + /// Constants (associated or generic) are irrelevant for this analysis, as their value is neither + /// affected by lifetimes, nor do they affect lifetimes. + pub fn is_fully_generic_for_reflection(self) -> bool { + #[derive(Default)] + struct ParamFinder { + seen: FxHashSet, + } + + impl<'tcx> TypeVisitor> for ParamFinder { + type Result = ControlFlow<()>; + fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { + match r.kind() { + RegionKind::ReEarlyParam(param) => { + if self.seen.insert(param.index) { + ControlFlow::Continue(()) + } else { + ControlFlow::Break(()) + } + } + RegionKind::ReBound(..) => ControlFlow::Continue(()), + RegionKind::ReStatic | RegionKind::ReError(_) => ControlFlow::Break(()), + RegionKind::ReVar(_) + | RegionKind::RePlaceholder(_) + | RegionKind::ReErased + | RegionKind::ReLateParam(_) => bug!("unexpected lifetime in impl: {r:?}"), + } + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + match t.kind() { + TyKind::Param(p) => { + // Reject using a parameter twice (e.g. in `Foo`) + if !self.seen.insert(p.index) { + return ControlFlow::Break(()); + } + } + TyKind::Alias(..) => return ControlFlow::Break(()), + _ => (), + } + t.super_visit_with(self) + } + } + self.trait_ref + .instantiate_identity() + .skip_norm_wip() + .visit_with(&mut ParamFinder::default()) + .is_continue() + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, StableHash, Debug)] #[derive(TypeFoldable, TypeVisitable, Default)] pub enum Asyncness { @@ -1178,6 +1237,7 @@ impl<'tcx> TypingEnv<'tcx> { let TypingEnv { typing_mode, param_env } = self; match typing_mode.0.assert_not_erased() { TypingMode::Coherence + | TypingMode::Reflection | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => {} @@ -1194,6 +1254,7 @@ impl<'tcx> TypingEnv<'tcx> { let TypingEnv { typing_mode, param_env } = self; match typing_mode.0.assert_not_erased() { TypingMode::Coherence + | TypingMode::Reflection | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 2b786b7e9e1a2..7adeebd235384 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -243,7 +243,7 @@ fn evaluate_candidate<'tcx>( return None; } - // We only handle: + // For now, we only handle: // ``` // bb4: { // _8 = discriminant((_3.1: Enum1)); @@ -262,41 +262,8 @@ fn evaluate_candidate<'tcx>( // When thie BB has exactly one statement, this statement should be discriminant. let need_hoist_discriminant = bbs[child].statements.len() == 1; + let otherwise_is_empty_unreachable = bbs[targets.otherwise()].is_empty_unreachable(); let child_place = if need_hoist_discriminant { - if !bbs[targets.otherwise()].is_empty_unreachable() { - // Someone could write code like this: - // ```rust - // let Q = val; - // if discriminant(P) == otherwise { - // let ptr = &mut Q as *mut _ as *mut u8; - // // It may be difficult for us to effectively determine whether values are valid. - // // Invalid values can come from all sorts of corners. - // unsafe { *ptr = 10; } - // } - // - // match P { - // A => match Q { - // A => { - // // code - // } - // _ => { - // // don't use Q - // } - // } - // _ => { - // // don't use Q - // } - // }; - // ``` - // - // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an - // invalid value, which is UB. - // In order to fix this, **we would either need to show that the discriminant computation of - // `place` is computed in all branches**. - // FIXME(#95162) For the moment, we adopt a conservative approach and - // consider only the `otherwise` branch has no statements and an unreachable terminator. - return None; - } // Handle: // ``` // bb4: { @@ -325,8 +292,7 @@ fn evaluate_candidate<'tcx>( }; *child_place }; - let destination = if need_hoist_discriminant || bbs[targets.otherwise()].is_empty_unreachable() - { + let destination = if otherwise_is_empty_unreachable { child_targets.otherwise() } else { targets.otherwise() @@ -340,6 +306,7 @@ fn evaluate_candidate<'tcx>( child_place, destination, need_hoist_discriminant, + otherwise_is_empty_unreachable, ) { return None; } @@ -359,11 +326,67 @@ fn verify_candidate_branch<'tcx>( place: Place<'tcx>, destination: BasicBlock, need_hoist_discriminant: bool, + otherwise_is_empty_unreachable: bool, ) -> bool { // In order for the optimization to be correct, the terminator must be a `SwitchInt`. let TerminatorKind::SwitchInt { discr: switch_op, targets } = &branch.terminator().kind else { return false; }; + if !otherwise_is_empty_unreachable { + // Someone could write code like this: + // ```rust + // let Q = val; + // if discriminant(P) == otherwise { + // let ptr = &mut Q as *mut _ as *mut u8; + // // It may be difficult for us to effectively determine whether values are valid. + // // Invalid values can come from all sorts of corners. + // unsafe { *ptr = 10; } + // } + // + // match P { + // A => match Q { + // A => { + // // code + // } + // _ => { + // // don't use Q + // } + // } + // _ => { + // // don't use Q + // } + // }; + // ``` + // + // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an + // invalid value, which is UB. + // In order to fix this, **we would either need to show that the discriminant computation of + // `place` is computed in all branches**. + // For , we adopt a conservative approach and + // consider only the `otherwise` branch has no statements and an unreachable terminator. + if need_hoist_discriminant { + return false; + } + // For : + // ``` + // bb0: { + // switchInt(copy _1) -> [1: bb1, 2: bb2, otherwise: bb5]; + // } + // bb1: { + // switchInt(copy (*_2)) -> [1: bb3, otherwise: bb5]; + // } + // bb2: { + // switchInt(copy (*_2)) -> [2: bb4, otherwise: bb5]; + // } + // ``` + // We cannot hoist the dereference of `_2` to `bb0`, + // because execution can reach `bb5` without dereferencing `_2`. + if let Some(place) = switch_op.place() + && !place.is_stable_offset() + { + return false; + } + } if need_hoist_discriminant { // If we need hoist discriminant, the branch must have exactly one statement. let [statement] = branch.statements.as_slice() else { diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 8b21e8284476b..c2c702dbf2470 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -802,6 +802,7 @@ where match self.elaborator.typing_env().typing_mode().assert_not_erased() { ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {} ty::TypingMode::Coherence + | ty::TypingMode::Reflection | ty::TypingMode::Typeck { .. } | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } => { diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 6d111ff44d415..040f98de7bcfd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -365,6 +365,11 @@ where goal: Goal, ) -> Result, NoSolutionOrRerunNonErased>; + fn consider_builtin_try_as_dyn_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolutionOrRerunNonErased>; + /// Consider (possibly several) candidates to upcast or unsize a type to another /// type, excluding the coercion of a sized type into a `dyn Trait`. /// @@ -483,6 +488,7 @@ where TypingMode::Coherence => true, TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen @@ -568,6 +574,14 @@ where let cx = self.cx(); let trait_def_id = goal.predicate.trait_def_id(cx); + // Builtin impls regularly are not `is_fully_generic_for_reflection`, so instead + // of trying to handle these manually, we just reject all builtin impls in reflection + // mode. We can probably lift this restriction for specific cases, but this is safer. + // See `try_as_dyn_builtin_impl` for how just allowing all builtin impls is unsound. + if self.typing_mode().is_reflection() { + return Ok(()); + } + // N.B. When assembling built-in candidates for lang items that are also // `auto` traits, then the auto trait candidate that is assembled in // `consider_auto_trait_candidate` MUST be disqualified to remain sound. @@ -660,6 +674,9 @@ where Some(SolverTraitLangItem::BikeshedGuaranteedNoDrop) => { G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal) } + Some(SolverTraitLangItem::TryAsDyn) => { + G::consider_builtin_try_as_dyn_candidate(self, goal) + } Some(SolverTraitLangItem::Field) => G::consider_builtin_field_candidate(self, goal), _ => Err(NoSolution.into()), } @@ -872,6 +889,14 @@ where return; } + // Builtin impls regularly are not `is_fully_generic_for_reflection`, so instead + // of trying to handle these manually, we just reject all builtin impls in reflection + // mode. We can probably lift this restriction for specific cases, but this is safer. + // See `try_as_dyn_builtin_impl` for how just allowing all builtin impls is unsound. + if self.typing_mode().is_reflection() { + return; + } + let self_ty = goal.predicate.self_ty(); let bounds = match self_ty.kind() { ty::Bool @@ -1066,6 +1091,7 @@ where | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Codegen => vec![], TypingMode::ErasedNotCoherence(MayBeErased) => { self.opaque_accesses diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 1c53bc7711ed8..df9758d5d2ab7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -451,6 +451,13 @@ where unreachable!("BikeshedGuaranteedNoDrop is not const"); } + fn consider_builtin_try_as_dyn_candidate( + _ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolutionOrRerunNonErased> { + unreachable!("`TryAsDynCompat` is not const: {:?}", goal) + } + fn consider_structural_builtin_unsize_candidates( _ecx: &mut EvalCtxt<'_, D>, _goal: Goal, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c3ccb46069063..16f8f3496d9e7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -566,28 +566,34 @@ where .entered(); let (result, orig_values, canonical_goal, succeeded_in_erased) = 'retry_canonicalize: { - let skip_erased_attempt = if typing_mode.is_coherence() { - true - } else { - let mut skip = false; - if opaque_types.iter().any(|(_, ty)| ty.is_ty_var()) - && let PredicateKind::Clause(ClauseKind::Trait(..)) = + let skip_erased_attempt = match typing_mode { + TypingMode::Reflection | TypingMode::Coherence => true, + TypingMode::Typeck { .. } + | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::PostBorrowck { .. } + | TypingMode::Codegen + | TypingMode::PostAnalysis + | TypingMode::ErasedNotCoherence(_) => { + let mut skip = false; + if opaque_types.iter().any(|(_, ty)| ty.is_ty_var()) + && let PredicateKind::Clause(ClauseKind::Trait(..)) = + goal.predicate.kind().skip_binder() + { + skip = true; + } + + if let PredicateKind::Clause(ClauseKind::Trait(tr)) = goal.predicate.kind().skip_binder() - { - skip = true; - } + && tr.self_ty().has_coroutines() + && self.cx().trait_is_auto(tr.trait_ref.def_id) + { + // FIXME(#155443): this doesn't make a difference now, but with eager normalization + // it likely will. + // skip_erased_attempt = true; + } - if let PredicateKind::Clause(ClauseKind::Trait(tr)) = - goal.predicate.kind().skip_binder() - && tr.self_ty().has_coroutines() - && self.cx().trait_is_auto(tr.trait_ref.def_id) - { - // FIXME(#155443): this doesn't make a difference now, but with eager normalization - // it likely will. - // skip_erased_attempt = true; + skip } - - skip }; if skip_erased_attempt { @@ -1649,9 +1655,10 @@ fn should_rerun_after_erased_canonicalization( // ============================= (RerunCondition::Always, _) => RerunDecision::Yes, // ============================= - (RerunCondition::OpaqueInStorage(..), TypingMode::PostAnalysis | TypingMode::Codegen) => { - RerunDecision::Yes - } + ( + RerunCondition::OpaqueInStorage(..), + TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::Reflection, + ) => RerunDecision::Yes, ( RerunCondition::OpaqueInStorage(defids), TypingMode::PostBorrowck { defined_opaque_types: opaques } @@ -1667,12 +1674,13 @@ fn should_rerun_after_erased_canonicalization( TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen + | TypingMode::Reflection | TypingMode::PostTypeckUntilBorrowck { .. }, ) => RerunDecision::No, // ============================= ( RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(_), - TypingMode::PostAnalysis | TypingMode::Codegen, + TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::Reflection, ) => RerunDecision::Yes, ( RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(defids), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index 582cd122c8ecf..069102f3db50b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -348,6 +348,7 @@ where | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis + | ty::TypingMode::Reflection | ty::TypingMode::Codegen => { ecx.instantiate_normalizes_to_as_rigid(goal)?; return ecx.evaluate_added_goals_and_make_canonical_response( @@ -1076,6 +1077,13 @@ where ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } + + fn consider_builtin_try_as_dyn_candidate( + _ecx: &mut EvalCtxt<'_, D>, + _goal: Goal, + ) -> Result, NoSolutionOrRerunNonErased> { + unreachable!("try_as_dyn helper trait doesn't have assoc types") + } } impl EvalCtxt<'_, D> diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs index 7524b2021c015..3387c8599b911 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs @@ -106,6 +106,7 @@ where TypingMode::Coherence | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Codegen => unreachable!(), } } @@ -149,7 +150,8 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } - TypingMode::PostAnalysis | TypingMode::Codegen => { + // FIXME(try_as_dyn): probably want to treat opaques opaquely and rigid + TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args); let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index 778826ba60aee..4918258350bf3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -70,6 +70,7 @@ where } TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 2ebea5d3eb188..f29df578cd97b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -10,9 +10,9 @@ use rustc_type_ir::solve::{ RerunReason, RerunResultExt, SizedTraitKind, }; use rustc_type_ir::{ - self as ty, FieldInfo, Interner, MayBeErased, Movability, PredicatePolarity, Region, - TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _, - elaborate, + self as ty, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability, + PredicatePolarity, Region, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, + Unnormalized, Upcast as _, elaborate, }; use tracing::{debug, instrument, trace, warn}; @@ -87,7 +87,15 @@ where // Impl matches polarity (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive) - | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes, + | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => { + if ecx.typing_mode().is_reflection() + && !cx.is_fully_generic_for_reflection(impl_def_id) + { + return Err(NoSolution.into()); + } else { + Certainty::Yes + } + } // Impl doesn't match polarity (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative) @@ -865,6 +873,49 @@ where } } + fn consider_builtin_try_as_dyn_candidate( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + ) -> Result, NoSolutionOrRerunNonErased> { + if goal.predicate.polarity != ty::PredicatePolarity::Positive { + return Err(NoSolution.into()); + } + let cx = ecx.cx(); + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + let self_ty = goal.predicate.self_ty(); + let ty_lifetime = goal.predicate.trait_ref.args.region_at(1); + match self_ty.kind() { + ty::Dynamic(bounds, lifetime) => { + for bound in bounds.iter() { + match bound.skip_binder() { + ExistentialPredicate::Trait(_) => {} + // FIXME(try_as_dyn): check what kind of projections we can allow + ExistentialPredicate::Projection(_) => return Err(NoSolution.into()), + // Auto traits do not affect lifetimes outside of specialization, + // which is disabled in reflection. + ExistentialPredicate::AutoTrait(_) => {} + } + } + ecx.add_goal( + GoalSource::Misc, + goal.with(cx, ty::OutlivesPredicate(ty_lifetime, lifetime)), + )?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + + ty::Bound(..) + | ty::Infer( + ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_), + ) => { + panic!("unexpected type `{self_ty:?}`") + } + + _ => Err(NoSolution.into()), + } + }) + } + fn consider_builtin_field_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -1607,6 +1658,7 @@ where } TypingMode::Coherence | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } => {} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7917478cc2c60..95421ba8cfdab 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2139,6 +2139,7 @@ symbols! { truncf32, truncf64, truncf128, + try_as_dyn, try_blocks, try_blocks_heterogeneous, try_capture, 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 2a1f0e7935ea0..b4f55e27048e2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5487,81 +5487,83 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if !matches!(tcx.def_kind(body_def_id), DefKind::Fn | DefKind::AssocFn) { return; } - let output = - tcx.fn_sig(body_def_id).instantiate_identity().skip_norm_wip().output().skip_binder(); - let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, args, .. }) = - output.kind() - else { - return; - }; - - // The predicate that reaches here has been rewritten through the impls it was - // derived from (e.g. `Iterator for Map` turns `Iterator::Item` requirements - // into requirements on `F`'s return type), so the associated types the user wrote - // in the signature are recovered from the opaque's bounds instead. - let mut probe_diffs = vec![]; - for clause in tcx.item_bounds(opaque_def_id).instantiate(tcx, args).skip_norm_wip() { - let Some(proj) = clause.as_projection_clause() else { continue }; - let proj = self.instantiate_binder_with_fresh_vars( - expr.span, - BoundRegionConversionTime::FnCall, - proj, - ); - let Some(expected_term) = proj.term.as_type() else { continue }; - // Only the projection (for its `DefId`) is used when probing the chain; the - // bound's own term is carried in `found` for the divergence check below and - // is replaced with the probed type afterwards. - probe_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { - expected: proj.projection_term.expect_ty().to_ty(tcx, ty::IsRigid::No), - found: expected_term, - })); - } - if probe_diffs.is_empty() { - return; - } - - // If the returned expression is a binding, walk the chain that created it instead. - let expr = if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind - && let hir::Path { res: Res::Local(hir_id), .. } = path - && let hir::Node::Pat(binding) = tcx.hir_node(*hir_id) - && let hir::Node::LetStmt(local) = tcx.parent_hir_node(binding.hir_id) - && let Some(binding_expr) = local.init - { - binding_expr - } else { - expr - }; - // Resolve what each bound associated type actually is for the returned expression, - // and keep only the ones that diverged from the signature. - let expr_ty = self.resolve_vars_if_possible( - typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), - ); - let assocs = self.probe_assoc_types_at_expr( - &probe_diffs, - expr.span, - expr_ty, - expr.hir_id, - param_env, - ); - let mut type_diffs = vec![]; - for (probe_diff, assoc) in iter::zip(probe_diffs, assocs) { - let TypeError::Sorts(ty::error::ExpectedFound { expected, found: expected_term }) = - probe_diff + let binder = tcx.fn_sig(body_def_id).instantiate_identity().skip_norm_wip().output(); + self.enter_forall(binder, |output| { + let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, args, .. }) = + output.kind() else { - continue; + return; }; - let Some((_, (_, actual_ty))) = assoc else { continue }; - if !self.can_eq(param_env, expected_term, actual_ty) { - type_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { - expected, - found: actual_ty, + + // The predicate that reaches here has been rewritten through the impls it was + // derived from (e.g. `Iterator for Map` turns `Iterator::Item` requirements + // into requirements on `F`'s return type), so the associated types the user wrote + // in the signature are recovered from the opaque's bounds instead. + let mut probe_diffs = vec![]; + for clause in tcx.item_bounds(opaque_def_id).instantiate(tcx, args).skip_norm_wip() { + let Some(proj) = clause.as_projection_clause() else { continue }; + let proj = self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + proj, + ); + let Some(expected_term) = proj.term.as_type() else { continue }; + // Only the projection (for its `DefId`) is used when probing the chain; the + // bound's own term is carried in `found` for the divergence check below and + // is replaced with the probed type afterwards. + probe_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { + expected: proj.projection_term.expect_ty().to_ty(tcx, ty::IsRigid::No), + found: expected_term, })); } - } - if !type_diffs.is_empty() { - self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); - } + if probe_diffs.is_empty() { + return; + } + + // If the returned expression is a binding, walk the chain that created it instead. + let expr = if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: Res::Local(hir_id), .. } = path + && let hir::Node::Pat(binding) = tcx.hir_node(*hir_id) + && let hir::Node::LetStmt(local) = tcx.parent_hir_node(binding.hir_id) + && let Some(binding_expr) = local.init + { + binding_expr + } else { + expr + }; + + // Resolve what each bound associated type actually is for the returned expression, + // and keep only the ones that diverged from the signature. + let expr_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), + ); + let assocs = self.probe_assoc_types_at_expr( + &probe_diffs, + expr.span, + expr_ty, + expr.hir_id, + param_env, + ); + let mut type_diffs = vec![]; + for (probe_diff, assoc) in iter::zip(probe_diffs, assocs) { + let TypeError::Sorts(ty::error::ExpectedFound { expected, found: expected_term }) = + probe_diff + else { + continue; + }; + let Some((_, (_, actual_ty))) = assoc else { continue }; + if !self.can_eq(param_env, expected_term, actual_ty) { + type_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { + expected, + found: actual_ty, + })); + } + } + if !type_diffs.is_empty() { + self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); + } + }); } /// If the type that failed selection is an array or a reference to an array, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 605f4d6758a5a..f5a30d2b26563 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -384,6 +384,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< TypingMode::Coherence | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => false, TypingMode::PostAnalysis | TypingMode::Codegen => { let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 8d5d8f26f9dce..a61c679c9870f 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -340,6 +340,7 @@ where TypingMode::Coherence | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => return Default::default(), }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 95f0c3dc9881d..4ec21b9f8a4cd 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -178,6 +178,7 @@ where TypingMode::Coherence | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => return Default::default(), }; diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 9364482a87cb8..b822c713bfabb 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -144,7 +144,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), - TypingMode::PostAnalysis | TypingMode::Codegen => {} + TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => {} } value.has_type_flags(flags) @@ -433,7 +433,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.super_fold_with(self), - TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e0edc76682a3b..79b531afbe2ae 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -991,6 +991,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( TypingMode::Coherence | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => { debug!( assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index ac6100747970e..fb15ed8a74c07 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.try_super_fold_with(self)?, - TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { let args = data.args.try_fold_with(self)?; let recursion_limit = self.cx().recursion_limit(); 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 a4f751e23d799..d4027fcf388b1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -15,7 +15,8 @@ use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, PredicateObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{ - self, FieldInfo, SizedTraitKind, TraitRef, Ty, TypeVisitableExt, elaborate, + self, ExistentialPredicate, FieldInfo, SizedTraitKind, TraitRef, Ty, TypeVisitableExt, + elaborate, }; use rustc_middle::{bug, span_bug}; use rustc_span::DUMMY_SP; @@ -132,6 +133,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut candidates, ); } + Some(LangItem::TryAsDyn) => { + self.assemble_candidates_for_try_as_dyn(obligation, &mut candidates); + } Some(LangItem::Field) => { self.assemble_candidates_for_field_trait(obligation, &mut candidates); } @@ -1457,6 +1461,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn assemble_candidates_for_try_as_dyn( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + match *obligation.predicate.self_ty().skip_binder().kind() { + ty::Dynamic(bounds, _lifetime) => { + for bound in bounds { + match bound.skip_binder() { + ExistentialPredicate::Trait(_) => {} + // FIXME(try_as_dyn): check what kind of projections we can allow + ExistentialPredicate::Projection(_) => return, + // Auto traits do not affect lifetimes outside of specialization, + // which is disabled in reflection. + ExistentialPredicate::AutoTrait(_) => {} + } + } + candidates.vec.push(TryAsDynCandidate); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + candidates.ambiguous = true; + } + + _ => {} + } + } + fn assemble_candidates_for_field_trait( &mut self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a7c84e71a68c5..49c277b39289b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -138,6 +138,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BikeshedGuaranteedNoDropCandidate => { self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation) } + + TryAsDynCandidate => self.confirm_try_as_dyn_candidate(obligation), }) } @@ -1315,4 +1317,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, obligations) } + + fn confirm_try_as_dyn_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + ) -> ImplSource<'tcx, PredicateObligation<'tcx>> { + let tcx = self.tcx(); + + let mut obligations = PredicateObligations::new(); + + let self_ty = obligation.predicate.self_ty(); + let ty_lifetime = obligation.predicate.map_bound(|p| p.trait_ref.args.region_at(1)); + + match *self_ty.skip_binder().kind() { + ty::Dynamic(_bounds, lifetime) => { + obligations.push( + obligation.with( + tcx, + ty_lifetime + .map_bound(|ty_lifetime| ty::OutlivesPredicate(ty_lifetime, lifetime)), + ), + ); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("unexpected type `{self_ty:?}`") + } + + _ => {} + } + ImplSource::Builtin(BuiltinImplSource::Misc, obligations) + } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7c9ae9246c96b..58f2d0c7f33ac 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -17,7 +17,7 @@ use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; -use rustc_infer::traits::{PredicateObligations, TraitObligation}; +use rustc_infer::traits::{ImplSource, PredicateObligations, TraitObligation}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::bug; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; @@ -282,6 +282,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(SelectionError::Overflow(OverflowError::Canonical)) } Err(e) => Err(e), + Ok(ImplSource::Builtin(..)) if self.typing_mode().is_reflection() => { + // Builtin impls regularly don't satisfy the try_as_dyn requirements, so + // we just reject all of them. + Err(SelectionError::Unimplemented) + } Ok(candidate) => Ok(Some(candidate)), } } @@ -1299,6 +1304,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match this.confirm_candidate(stack.obligation, candidate.clone()) { Ok(selection) => { debug!(?selection); + if let ImplSource::Builtin(..) = selection + && this.typing_mode().is_reflection() + { + return Ok(EvaluatedToErr); + } this.evaluate_predicates_recursively( stack.list(), selection.nested_obligations().into_iter(), @@ -1485,6 +1495,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TypingMode::Coherence => {} TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen => return Ok(()), @@ -1536,6 +1547,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { defining_opaque_types.is_empty() || (!pred.has_opaque_types() && !pred.has_coroutines()) } + // Impls that are not fully generic are completely ignored as "nonexistent" + // in this mode, so the results wildly differ from normal trait solving. + TypingMode::Reflection => false, // The hidden types of `defined_opaque_types` is not local to the current // inference context, so we can freely move this to the global cache. TypingMode::PostBorrowck { .. } => true, @@ -2059,6 +2073,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitUpcastingUnsizeCandidate(_) | BuiltinObjectCandidate | BuiltinUnsizeCandidate + | TryAsDynCandidate | BikeshedGuaranteedNoDropCandidate => false, // Non-global param candidates have already been handled, global // where-bounds get ignored. @@ -2569,11 +2584,27 @@ impl<'tcx> SelectionContext<'_, 'tcx> { })?; nested_obligations.extend(obligations); - if impl_trait_header.polarity == ty::ImplPolarity::Reservation - && !self.typing_mode().is_coherence() - { - debug!("reservation impls only apply in intercrate mode"); - return Err(()); + match self.typing_mode() { + TypingMode::Coherence => {} + TypingMode::Reflection + if !self.tcx().impl_is_fully_generic_for_reflection(impl_def_id) => + { + debug!("reflection mode only allows fully generic impls"); + return Err(()); + } + + TypingMode::Typeck { .. } + | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::PostBorrowck { .. } + | TypingMode::Codegen + | TypingMode::ErasedNotCoherence(_) + | TypingMode::Reflection + | TypingMode::PostAnalysis => { + if impl_trait_header.polarity == ty::ImplPolarity::Reservation { + debug!("reservation impls only apply in intercrate mode"); + return Err(()); + } + } } Ok(Normalized { value: impl_args, obligations: nested_obligations }) @@ -2916,6 +2947,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } TypingMode::Coherence | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } => false, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index d9069ac127729..b5a82793dcc97 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -167,6 +167,7 @@ fn resolve_associated_item<'tcx>( ty::TypingMode::Coherence | ty::TypingMode::Typeck { .. } | ty::TypingMode::PostTypeckUntilBorrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostBorrowck { .. } => false, ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => { !trait_ref.still_further_specializable() diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index abec1850502b6..7a53fe1e0cfc8 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -87,6 +87,7 @@ fn layout_of<'tcx>( | ty::TypingMode::Typeck { .. } | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::ErasedNotCoherence(_) | ty::TypingMode::PostAnalysis => {} } @@ -552,6 +553,7 @@ fn layout_of_uncached<'tcx>( | ty::TypingMode::Typeck { .. } | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::ErasedNotCoherence(_) | ty::TypingMode::PostAnalysis => { return Err(error(cx, LayoutError::TooGeneric(ty))); diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 75f906e498eda..c652119957dd4 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -123,6 +123,10 @@ pub enum TypingMode { /// This is currently only used by the new solver, but should be implemented in /// the old solver as well. PostBorrowck { defined_opaque_types: I::LocalDefIds }, + /// During the evaluation of reflection logic that ignores lifetimes, we can only + /// handle impls that are fully generic over all lifetimes without constraints on + /// those lifetimes (other than implied bounds). + Reflection, /// After analysis, mostly during MIR optimizations, we're able to /// reveal all opaque types. As the hidden type should *never* be observable /// directly by the user, this should not be used by checks which may expose @@ -173,6 +177,7 @@ impl PartialEq for TypingModeEqWrapper { fn eq(&self, other: &Self) -> bool { match (self.0, other.0) { (TypingMode::Coherence, TypingMode::Coherence) => true, + (TypingMode::Reflection, TypingMode::Reflection) => true, ( TypingMode::Typeck { defining_opaque_types_and_generators: l }, TypingMode::Typeck { defining_opaque_types_and_generators: r }, @@ -193,6 +198,7 @@ impl PartialEq for TypingModeEqWrapper { ) => true, ( TypingMode::Coherence + | TypingMode::Reflection | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } @@ -218,6 +224,25 @@ impl TypingMode { TypingMode::Coherence => true, TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection + | TypingMode::PostBorrowck { .. } + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::ErasedNotCoherence(_) => false, + } + } + + /// There are a bunch of places in the compiler where we single out `Reflection`, + /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively, + /// but not having this method leads to a bunch of noisy code. + /// + /// See also the documentation on [`TypingMode`] about exhaustive matching. + pub fn is_reflection(&self) -> bool { + match self { + TypingMode::Reflection => true, + TypingMode::Typeck { .. } + | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Coherence | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen @@ -236,6 +261,7 @@ impl TypingMode { TypingMode::Coherence | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen => false, @@ -262,6 +288,7 @@ impl TypingMode { } TypingMode::PostAnalysis => TypingMode::PostAnalysis, TypingMode::Codegen => TypingMode::Codegen, + TypingMode::Reflection => TypingMode::Reflection, TypingMode::ErasedNotCoherence(MayBeErased) => panic!( "Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible" ), @@ -327,6 +354,7 @@ impl From> for TypingMode TypingMode::PostAnalysis, TypingMode::Codegen => TypingMode::Codegen, + TypingMode::Reflection => TypingMode::Reflection, } } } @@ -563,6 +591,7 @@ where TypingMode::Coherence | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol), TypingMode::Codegen => true, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 565414fdd58e3..bfa1c982bd0b7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -423,6 +423,8 @@ pub trait Interner: fn impl_polarity(self, impl_def_id: Self::ImplId) -> ty::ImplPolarity; + fn is_fully_generic_for_reflection(self, impl_def_id: Self::ImplId) -> bool; + fn trait_is_auto(self, trait_def_id: Self::TraitId) -> bool; fn trait_is_coinductive(self, trait_def_id: Self::TraitId) -> bool; diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs index 05f9bb382dc38..1671128e67a3a 100644 --- a/compiler/rustc_type_ir/src/lang_items.rs +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -54,6 +54,7 @@ pub enum SolverTraitLangItem { Sized, TransmuteTrait, TrivialClone, + TryAsDyn, Tuple, Unpin, Unsize, diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index b4ec6dbf5126d..e42e96901b74d 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -914,6 +914,7 @@ fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling< | TypingMode::ErasedNotCoherence { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } + | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => (), }; diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 9ac4cd2dddc81..66eb27074ee30 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -180,6 +180,7 @@ where Ok(a) } TypingMode::Typeck { .. } + | TypingMode::Reflection | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 6c8cb114b9ef1..85ff2fe1dd6ee 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -86,7 +86,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::intrinsics::{self, type_id_vtable}; +use crate::intrinsics::{self, type_id, type_id_vtable}; use crate::mem::transmute; use crate::mem::type_info::{TraitImpl, TypeKind}; use crate::{fmt, hash, ptr}; @@ -786,12 +786,10 @@ impl TypeId { #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] - pub fn trait_info_of> + ?Sized + 'static>( - self, - ) -> Option> { + pub fn trait_info_of<'a, T: TryAsDynCompatible<'a> + ?Sized>(self) -> Option> { // SAFETY: The vtable was obtained for `T`, so it is guaranteed to be `DynMetadata`. // The intrinsic can't infer this because it is designed to work with arbitrary TypeIds. - unsafe { transmute(self.trait_info_of_trait_type_id(const { TypeId::of::() })) } + unsafe { transmute(self.trait_info_of_trait_type_id(const { type_id::() })) } } /// Checks if the [TypeId] implements the trait of `trait_represented_by_type_id`. If it does it returns [TraitImpl] which can be used to build a fat pointer. @@ -948,12 +946,72 @@ pub const fn type_name_of_val(_val: &T) -> &'static str { type_name::() } -/// Returns `Some(&U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`. +/// Trait that is automatically implemented for all `dyn Trait<'b, C> + 'a` without assoc type bounds. +/// The lifetime parameter should be the same that is used to constrain generic type parameters +/// that are turned into the dyn trait constrained by `TryAsDynCompatible`. +/// +/// This is required for `try_as_dyn` to be able to soundly convert non-static +/// types to `dyn Trait`. +/// +/// Note: these requirements are sufficient for soundness, but it is unclear +/// if they are all necessary. We may be able to lift some requirements in favor +/// of more precise ones. +/// +#[unstable(feature = "try_as_dyn", issue = "144361")] +#[lang = "try_as_dyn"] +#[rustc_deny_explicit_impl] +pub trait TryAsDynCompatible<'a>: ptr::Pointee> {} + +/// Returns `Some(&U)` if `T` can be coerced to the dyn trait type `U`. Otherwise, it returns `None`. +/// +/// # Run-time failures +/// +/// There are multiple ways to get a `None`, and you need to manually analyze which one it is, as the +/// compiler does not provide any help here. +/// +/// * `T` does not implement `Trait` at all, +/// * `T`'s impl for `Trait` is not fully generic, +/// * `T`'s impl for `Trait` is a builtin impl (e.g. `dyn Debug` implements `Debug`) +/// +/// There is some detailed documentation about this feature at +/// +/// But the gist is summarized below: +/// +/// ## Lifetime-independent impls +/// +/// `try_as_dyn` does not have access to lifetime information, thus it cannot differentiate between +/// `'static`, other lifetimes, and can't reason about outlives bounds on impls. Thus we can only accept +/// impls that do not have `'static` lifetimes, or outlives bounds of any kind. You can have simple +/// trait bounds, and the compiler will transitively only use impls of those simple trait bounds that satisfy +/// the same rules as the main trait you're converting to. +/// +/// An example of a legal impl is: +/// +/// ```rust +/// # trait Trait<'a, T> {} +/// # struct Type<'b, U>(&'b U); +/// # use std::fmt::{Debug, Display}; +/// impl<'a, 'b, T: Debug, U: Display> Trait<'a, T> for Type<'b, U> {} +/// ``` +/// +/// Impls without generic parameters at all are also legal, as long as they contain no `'static` lifetimes. +/// +/// ## Builtin impls +/// +/// Builtin impls (like `impl Debug for dyn Debug`) have various obscure rules and often are not fully generic. +/// To simplify reasoning about what is allowed and what not, all builtin impls are rejected and will neither +/// directly nor indirectly contribute to a `Some` result. /// /// # Compile-time failures -/// Determining whether `T` can be coerced to the trait object type `U` requires compiler trait resolution. +/// Determining whether `T` can be coerced to the dyn trait type `U` requires compiler trait resolution. /// In some cases, that resolution can exceed the recursion limit, /// and compilation will fail instead of this function returning `None`. +/// +/// The input type `T` must outlive the lifetime `'a` on the `dyn Trait + 'a`. +/// This is basically the same rule that forbids `let x: &dyn Trait + 'static = &&some_local_variable;` +/// So if you see borrow check errors around `try_as_dyn`, think about whether a normal unsizing +/// coercion would be possible at all if you were using concrete types or had bounds on the input type. +/// /// # Examples /// /// ```rust @@ -983,17 +1041,14 @@ pub const fn type_name_of_val(_val: &T) -> &'static str { /// ``` #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] -pub const fn try_as_dyn< - T: Any + ?Sized + 'static, - U: ptr::Pointee> + ?Sized + 'static, ->( +pub const fn try_as_dyn<'a, T: ?Sized + 'a, U: TryAsDynCompatible<'a> + ?Sized>( t: &T, ) -> Option<&U> { // For unsized `T`, `trait_info_of` always returns `None` (vtable lookup is // only supported for sized types). The function therefore unconditionally // returns `None` in that case. let vtable: Option> = - const { TypeId::of::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; + const { type_id::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; match vtable { Some(dyn_metadata) => { let pointer = ptr::from_raw_parts(t as *const T as *const (), dyn_metadata); @@ -1009,50 +1064,17 @@ pub const fn try_as_dyn< /// Returns `Some(&mut U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`. /// -/// # Compile-time failures -/// Determining whether `T` can be coerced to the trait object type `U` requires compiler trait resolution. -/// In some cases, that resolution can exceed the recursion limit, -/// and compilation will fail instead of this function returning `None`. -/// # Examples -/// -/// ```rust -/// #![feature(try_as_dyn)] -/// -/// use core::any::try_as_dyn_mut; -/// -/// trait Animal { -/// fn speak(&self) -> &'static str; -/// } -/// -/// struct Dog; -/// impl Animal for Dog { -/// fn speak(&self) -> &'static str { "woof" } -/// } -/// -/// struct Rock; // does not implement Animal -/// -/// let mut dog = Dog; -/// let mut rock = Rock; -/// -/// let as_animal: Option<&mut dyn Animal> = try_as_dyn_mut::(&mut dog); -/// assert_eq!(as_animal.unwrap().speak(), "woof"); -/// -/// let not_an_animal: Option<&mut dyn Animal> = try_as_dyn_mut::(&mut rock); -/// assert!(not_an_animal.is_none()); -/// ``` +/// See documentation of [try_as_dyn] for details about the behaviour and limitations. #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] -pub const fn try_as_dyn_mut< - T: Any + ?Sized + 'static, - U: ptr::Pointee> + ?Sized + 'static, ->( +pub const fn try_as_dyn_mut<'a, T: ?Sized + 'a, U: TryAsDynCompatible<'a> + ?Sized>( t: &mut T, ) -> Option<&mut U> { // For unsized `T`, `trait_info_of` always returns `None` (vtable lookup is // only supported for sized types). The function therefore unconditionally // returns `None` in that case. let vtable: Option> = - const { TypeId::of::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; + const { type_id::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; match vtable { Some(dyn_metadata) => { let pointer = ptr::from_raw_parts_mut(t as *mut T as *mut (), dyn_metadata); diff --git a/library/coretests/tests/mem/trait_info_of.rs b/library/coretests/tests/mem/trait_info_of.rs index c723a96095815..4fd4a013693d9 100644 --- a/library/coretests/tests/mem/trait_info_of.rs +++ b/library/coretests/tests/mem/trait_info_of.rs @@ -10,6 +10,7 @@ impl Blah for Garlic { self.0 * 21 } } +unsafe impl Send for Garlic {} #[test] fn test_implements_trait() { diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index f930573748e28..25a5238f538ee 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -7fb284d9037fa54f6a9b24261c82b394472cbfd7 +390279b302ca98ae270f434100ae3730531d1246 diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index bf2de84575d69..3b6d0a5032974 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -86,7 +86,7 @@ - [Debugging bootstrap](./building/bootstrapping/debugging-bootstrap.md) - [cfg(bootstrap) in dependencies](./building/bootstrapping/bootstrap-in-dependencies.md) -# High-level Compiler Architecture +# High-level compiler architecture - [Prologue](./part-2-intro.md) - [Overview of the compiler](./overview.md) @@ -115,7 +115,7 @@ - [Autodiff flags](./autodiff/flags.md) - [Type Trees](./autodiff/type-trees.md) -# Source Code Representation +# Source code representation - [Prologue](./part-3-intro.md) - [Syntax and the AST](./syntax-intro.md) @@ -140,7 +140,7 @@ - [MIR queries and passes: getting the MIR](./mir/passes.md) - [Inline assembly](./asm.md) -# Supporting Infrastructure +# Supporting infrastructure - [Command-line arguments](./cli.md) - [rustc_driver and rustc_interface](./rustc-driver/intro.md) @@ -167,8 +167,8 @@ - [ADTs and Generic Arguments](./ty-module/generic-arguments.md) - [Parameter types/consts/regions](./ty-module/param-ty-const-regions.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) -- [Aliases and Normalization](./normalization.md) -- [Typing/Param Envs](./typing-parameter-envs.md) +- [Aliases and normalization](./normalization.md) +- [Typing/Param envs](./typing-parameter-envs.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) @@ -199,7 +199,7 @@ - [HIR Type checking](./hir-typeck/summary.md) - [Coercions](./hir-typeck/coercions.md) - [Method lookup](./hir-typeck/method-lookup.md) -- [Const Generics](./const-generics.md) +- [Const generics](./const-generics.md) - [Opaque types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) @@ -239,18 +239,18 @@ - [Debugging LLVM](./backend/debugging.md) - [Backend Agnostic Codegen](./backend/backend-agnostic.md) - [Implicit caller location](./backend/implicit-caller-location.md) -- [Debug Info](./debuginfo/intro.md) - - [Rust Codegen](./debuginfo/rust-codegen.md) - - [LLVM Codegen](./debuginfo/llvm-codegen.md) - - [Debugger Internals](./debuginfo/debugger-internals.md) - - [LLDB Internals](./debuginfo/lldb-internals.md) - - [GDB Internals](./debuginfo/gdb-internals.md) - - [Debugger Visualizers](./debuginfo/debugger-visualizers.md) +- [Debug info](./debuginfo/intro.md) + - [Rust codegen](./debuginfo/rust-codegen.md) + - [LLVM codegen](./debuginfo/llvm-codegen.md) + - [Debugger internals](./debuginfo/debugger-internals.md) + - [LLDB internals](./debuginfo/lldb-internals.md) + - [GDB internals](./debuginfo/gdb-internals.md) + - [Debugger visualizers](./debuginfo/debugger-visualizers.md) - [LLDB - Python Providers](./debuginfo/lldb-visualizers.md) - [GDB - Python Providers](./debuginfo/gdb-visualizers.md) - [CDB - Natvis](./debuginfo/natvis-visualizers.md) - [Testing](./debuginfo/testing.md) - - [(Lecture Notes) Debugging support in the Rust compiler](./debugging-support-in-rustc.md) + - [(Lecture notes) Debugging support in the Rust compiler](./debugging-support-in-rustc.md) - [Libraries and metadata](./backend/libs-and-metadata.md) - [Profile-guided optimization](./profile-guided-optimization.md) - [LLVM source-based code coverage](./llvm-coverage-instrumentation.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 56fbc1f6b7a85..6282a66e13b07 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -1,5 +1,7 @@ # About this guide + + This guide is meant to help document how rustc – the Rust compiler – works, as well as to help new contributors get involved in rustc development. @@ -14,18 +16,18 @@ There are several parts to this guide: 1. [Bootstrapping][p3]: Describes how the Rust compiler builds itself using previous versions, including an introduction to the bootstrap process and debugging methods. -1. [High-level Compiler Architecture][p4]: +1. [High-level compiler architecture][p4]: Discusses the high-level architecture of the compiler and stages of the compile process. -1. [Source Code Representation][p5]: +1. [Source code representation][p5]: Describes the process of taking raw source code from the user and transforming it into various forms that the compiler can work with easily. -1. [Supporting Infrastructure][p6]: +1. [Supporting infrastructure][p6]: Covers command-line argument conventions, compiler entry points like rustc_driver and rustc_interface, and the design and implementation of errors and lints. 1. [Analysis][p7]: Discusses the analyses that the compiler uses to check various properties of the code and inform later stages of the compile process (e.g., type checking). -1. [MIR to Binaries][p8]: How linked executable machine code is generated. +1. [Mir to binaries][p8]: How linked executable machine code is generated. 1. [Appendices][p9] at the end with useful reference information. There are a few of these with different information, including a glossary. diff --git a/src/doc/rustc-dev-guide/src/autodiff/installation.md b/src/doc/rustc-dev-guide/src/autodiff/installation.md index c0da9621f9777..acbb7c9eb09f3 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/installation.md +++ b/src/doc/rustc-dev-guide/src/autodiff/installation.md @@ -20,7 +20,7 @@ rustup +nightly component add enzyme Older rustup versions are not aware of this component, so if you run into issues try updating rustup itself: ```console -rustup update +rustup self update rustup +nightly component add enzyme ``` diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 3f84b99fb637e..9e26a174d8cf6 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -1,4 +1,4 @@ -# Const Generics +# Const generics ## Kinds of const arguments @@ -15,9 +15,9 @@ Inference Variables are quite boring and treated equivalently to type inference Const Parameters are also similarly boring and equivalent to uses of type parameters almost everywhere. However, there are some interesting subtleties with how they are handled during parsing, name resolution, and AST lowering: [ambig-unambig-ty-and-consts]. -## Anon Consts +## Anon consts -Anon Consts (short for anonymous const items) are how arbitrary expression are represented in const generics, for example an array length of `1 + 1` or `foo()` or even just `0`. +Anon consts (short for anonymous const items) are how arbitrary expression are represented in const generics, for example an array length of `1 + 1` or `foo()` or even just `0`. These are unique to const generics and have no real type equivalent. ### Desugaring @@ -85,7 +85,7 @@ After all of this desugaring has taken place the final representation in the typ This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. -### Enforcing lack of Generic Parameters +### Enforcing lack of generic parameters There are three ways that we enforce anon consts can't use generic parameters: 1. Name Resolution will not resolve paths to generic parameters when inside of an anon const @@ -134,7 +134,9 @@ fn foo() { } ``` -However, to avoid most of the problems involved in allowing generic parameters in anon const const arguments we require that the constant be evaluated before monomorphization (e.g. during type checking). In some sense we only allow generic parameters here when they are semantically unused. +However, to avoid most of the problems involved in allowing generic parameters in anon const const arguments, +we require that the constant be evaluated before monomorphization (e.g. during type checking). +In some sense we only allow generic parameters here when they are semantically unused. In the previous example the anon const can be evaluated for any type parameter `T` because raw pointers to sized types always have the same size (e.g. `8` on 64bit platforms). @@ -182,7 +184,7 @@ It is currently unclear what the right way to make `generic_const_parameter_type `min_generic_const_args` will allow for some expressions (for example array construction) to be representable without an anon const and therefore without running into these issues, though whether this is *enough* has yet to be determined. -## Checking types of Const Arguments +## Checking types of const arguments In order for a const argument to be well formed it must have the same type as the const parameter it is an argument to. For example, a const argument of type `bool` for an array length is not well formed, as an array's length parameter has type `usize`. diff --git a/src/doc/rustc-dev-guide/src/debuginfo/CodeView.pdf b/src/doc/rustc-dev-guide/src/debuginfo/CodeView.pdf deleted file mode 100644 index f899d25178458..0000000000000 Binary files a/src/doc/rustc-dev-guide/src/debuginfo/CodeView.pdf and /dev/null differ diff --git a/src/doc/rustc-dev-guide/src/debuginfo/debugger-internals.md b/src/doc/rustc-dev-guide/src/debuginfo/debugger-internals.md index 114ce8a998c58..3da43fe898dae 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/debugger-internals.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/debugger-internals.md @@ -1,14 +1,16 @@ -# Debugger Internals +# Debugger internals -It is the debugger's job to convert the debug info into an in-memory representation. Both the -interpretation of the debug info and the in-memory representation are arbitrary; anything will do -so long as meaningful information can be reconstructed while the program is running. The pipeline -from raw debug info to usable types can be quite complicated. +It is the debugger's job to convert the debug info into an in-memory representation. +Both the interpretation of the debug info and the in-memory representation are arbitrary; +anything will do, +so long as meaningful information can be reconstructed while the program is running. +The pipeline from raw debug info to usable types can be quite complicated. Once the information is in a workable format, the debugger front-end then must provide a way to interpret and display the data, a way for users to interact with it, and an API for extensibility. -Debuggers are vast systems and cannot be covered completely here. This section will provide a brief -overview of the subsystems directly relevant to the Rust debugging experience. +Debuggers are vast systems and cannot be covered completely here. +This section will provide a brief overview of the subsystems +directly relevant to the Rust debugging experience. -Microsoft's debugging engine is closed source, so it will not be covered here. \ No newline at end of file +Microsoft's debugging engine is closed source, so it will not be covered here. diff --git a/src/doc/rustc-dev-guide/src/debuginfo/debugger-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/debugger-visualizers.md index 831acbd2f8f8e..10167bf69cedc 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/debugger-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/debugger-visualizers.md @@ -1,42 +1,47 @@ -# Debugger Visualizers +# Debugger visualizers These are typically the last step before the debugger displays the information, but the results may be piped through a debug adapter such as an IDE's debugger API. -The term "Visualizer" is a bit of a misnomer. The real goal isn't just to prettify the output, but -to provide an interface for the user to interact with that is as useful as possible. In many cases -this means reconstructing the original type as closely as possible to its Rust representation, but -not always. +The term "Visualizer" is a bit of a misnomer. +The real goal isn't just to prettify the output, but +to provide an interface for the user to interact with that is as useful as possible. +In many cases, +this means reconstructing the original type as closely as possible to its Rust representation, +but not always. The visualizer interface allows generating "synthetic children" - fields that don't exist in the -debug info, but can be derived from invariants about the language and the type itself. A simple -example is allowing one to interact with the elements of a `Vec` instead of just it's `*mut u8` -heap pointer, length, and capacity. +debug info, but can be derived from invariants about the language and the type itself. +A simple example is allowing one to interact with the elements of a `Vec` +instead of just it's `*mut u8` heap pointer, length, and capacity. ## `rust-lldb`, `rust-gdb`, and `rust-windbg.cmd` -These support scripts are distributed with Rust toolchains. They locate the appropriate debugger and +These support scripts are distributed with Rust toolchains. +They locate the appropriate debugger and the toolchain's visualizer scripts, then launch the debugger with the appropriate arguments to load the visualizer scripts before a debugee is launched/attached to. ## `#![debugger_visualizer]` [This attribute][dbg_vis_attr] allows Rust library authors to include pretty printers for their -types within the library itself. These pretty printers are of the same format as typical -visualizers, but are embedded directly into the compiled binary. These scripts are loaded -automatically by the debugger, allowing a seamless experience for users. This attribute currently -works for GDB and natvis scripts. +types within the library itself. +These pretty printers are of the same format as typical +visualizers, but are embedded directly into the compiled binary. +These scripts are loaded automatically by the debugger, allowing a seamless experience for users. +This attribute currently works for GDB and natvis scripts. [dbg_vis_attr]: https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute -GDB python scripts are embedded in the `.debug_gdb_scripts` section of the binary. More information -can be found [here](https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html). Rustc accomplishes this in [`rustc_codegen_llvm/src/debuginfo/gdb.rs`][gdb_rs] +GDB python scripts are embedded in the `.debug_gdb_scripts` section of the binary ([more info]). +Rustc accomplishes this in [`rustc_codegen_llvm/src/debuginfo/gdb.rs`][gdb_rs]. +[more info]: https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html [gdb_rs]: https://github.com/rust-lang/rust/blob/main/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs Natvis files can be embedded in the PDB debug info using the [`/NATVIS` linker option][linker_opt], -and have the [highest priority][priority] when a type is resolving which visualizer to use. The -files specified by the attribute are collected into +and have the [highest priority][priority] when a type is resolving which visualizer to use. +The files specified by the attribute are collected into [`CrateInfo::natvis_debugger_visualizers`][natvis] which are then added as linker arguments in [`rustc_codegen_ssa/src/back/linker.rs`][linker_rs] @@ -46,27 +51,32 @@ files specified by the attribute are collected into [linker_rs]: https://github.com/rust-lang/rust/blob/main/compiler/rustc_codegen_ssa/src/back/linker.rs#L1106 LLDB is not currently supported, but there are a few methods that could potentially allow support in -the future. Officially, the intended method is via a [formatter bytecode][bytecode]. This was -created to offer a comparable experience to GDB's, but without the safety concerns associated with -embedding an entire python script. The opcodes are limited, but it works with `SBValue` and `SBType` -in roughly the same way as python visualizer scripts. Implementing this would require writing some -sort of DSL/mini compiler. +the future. +Officially, the intended method is via a [formatter bytecode][bytecode]. +This was created to offer a comparable experience to GDB's, +but without the safety concerns associated with embedding an entire Python script. +The opcodes are limited, but it works with `SBValue` and `SBType` +in roughly the same way as Python visualizer scripts. +Implementing this would require writing some sort of DSL/mini compiler. [bytecode]: https://lldb.llvm.org/resources/formatterbytecode.html Alternatively, it might be possible to copy GDB's strategy entirely: create a bespoke section in the -binary and embed a python script in it. LLDB will not load it automatically, but the python API does -allow one to access the [raw sections of the debug info][SBSection]. With this, it may be possible -to extract the python script from our bespoke section and then load it in during the startup of -Rust's visualizer scripts. +binary and embed a python script in it. +LLDB will not load it automatically, but the Python API does +allow one to access the [raw sections of the debug info][SBSection]. +With this, it may be possible to extract the Python script from our bespoke section +and then load it in during the startup of Rust's visualizer scripts. [SBSection]: https://lldb.llvm.org/python_api/lldb.SBSection.html#sbsection ## Performance Before tackling the visualizers themselves, it's important to note that these are part of a -performance-sensitive system. Please excuse the break in formality, but: if I have to spend -significant time debugging, I'm annoyed. If I have to *wait on my debugger*, I'm pissed. +performance-sensitive system. +Please excuse the break in formality, but: if I have to spend +significant time debugging, I'm annoyed. +If I have to *wait on my debugger*, I'm pissed. Every millisecond spent in these visualizers is a millisecond longer for the user to see output. This can be especially painful for large stackframes that contain many/large container types. @@ -75,37 +85,45 @@ delays of tens of seconds (or even minutes) before being able to interact with a frame. There is a tendancy to balk at the idea of optimizing Python code, but it really can have a -substantial impact. Remember, there is no compiler to help keep the code fast. Even simple -transformations are not done for you. It can be difficult to find Python performance tips through +substantial impact. +Remember, there is no compiler to help keep the code fast. +Even simple transformations are not done for you. +It can be difficult to find Python performance tips through all the noise of people suggesting you don't bother optimizing Python, so here are some things to keep in mind that are relevant to these scripts: * Everything allocates, even `int` -* Use tuples when possible. `list` is effectively `Vec>`, whereas tuples are equivalent -to `Box<[Any]>`. They have one less layer of indirection, don't carry extra capacity and can't -grow/shrink which can be advantageous in many cases. An additional benefit is that Python caches and -recycles the underlying allocations of all tuples up to size 20. +* Use tuples when possible. + `list` is effectively `Vec>`, whereas tuples are equivalent to `Box<[Any]>`. + They have one less layer of indirection, don't carry extra capacity and can't grow/shrink, + which can be advantageous in many cases. + An additional benefit is that Python caches and + recycles the underlying allocations of all tuples up to size 20. * Regexes are slow and should be avoided when simple string manipulation will do * Strings are immutable, thus many string operations implictly copy the contents. * When concatenating large lists of strings, `"".join(iterable_of_strings)` is typically the fastest -way to do it. + way to do it. * f-strings are generally the fastest way to do small, simple string transformations such as surrounding a string with parentheses. -* The act of calling a function is somewhat slow (even if the function is completely empty). If the -code section is very hot, consider inlining the function manually. +* The act of calling a function is somewhat slow (even if the function is completely empty). + If the code section is very hot, consider inlining the function manually. * Local variable access is significantly faster than global and built-in function access * Member/method access via the `.` operator is also slow, consider reassigning deeply nested values -to local variables to avoid this cost (e.g. `h = a.b.c.d.e.f.g.h`). + to local variables to avoid this cost (e.g. `h = a.b.c.d.e.f.g.h`). * Accessing inherited methods and fields is about 2x slower than base-class methods and fields. -Avoid inheritance whenever possible. -* Use [`__slots__`](https://wiki.python.org/moin/UsingSlots) wherever possible. `__slots__` is a way -to indicate to Python that your class's fields won't change and speeds up field access by a -noticable amount. This does require you to name your fields in advance and initialize them in -`__init__`, but it's a small price to pay for the benefits. -* Match statements/if..elif..else are not optimized in any way. The conditions are checked in order, -1 by 1. If possible, use an alternative such as dictionary dispatch or a table of values + Avoid inheritance whenever possible. +* Use [`__slots__`](https://wiki.python.org/moin/UsingSlots) wherever possible. + `__slots__` is a way + to indicate to Python that your class's fields won't change and speeds up field access by a + noticable amount. + This does require you to name your fields in advance and initialize them in + `__init__`, but it's a small price to pay for the benefits. +* Match statements/if..elif..else are not optimized in any way. + The conditions are checked in order, 1 by 1. + If possible, use an alternative such as dictionary dispatch or a table of values * Compute lazily when possible * List comprehensions are typically faster than loops, generator comprehensions are a bit slower -than list comprehensions, but use less memory. You can think of comprehensions as equivalent to -Rust's `iter.map()`. List comprehensions effectively call `collect::>` at the end, whereas -generator comprehensions do not. \ No newline at end of file + than list comprehensions, but use less memory. + You can think of comprehensions as equivalent to Rust's `iter.map()`. + List comprehensions effectively call `collect::>` at the end, whereas + generator comprehensions do not. diff --git a/src/doc/rustc-dev-guide/src/debuginfo/gdb-internals.md b/src/doc/rustc-dev-guide/src/debuginfo/gdb-internals.md index 95f543c8e94a0..2b80521f4519e 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/gdb-internals.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/gdb-internals.md @@ -1,4 +1,4 @@ -# (WIP) GDB Internals +# GDB internals -GDB's Rust support lives at `gdb/rust-lang.h` and `gdb/rust-lang.c`. The expression parsing support -can be found in `gdb/rust-exp.h` and `gdb/rust-parse.c` \ No newline at end of file +GDB's Rust support lives at `gdb/rust-lang.h` and `gdb/rust-lang.c`. +The expression parsing support can be found in `gdb/rust-exp.h` and `gdb/rust-parse.c` diff --git a/src/doc/rustc-dev-guide/src/debuginfo/gdb-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/gdb-visualizers.md index 4027ef897f28a..3f8fb3bf439a5 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/gdb-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/gdb-visualizers.md @@ -1,4 +1,4 @@ -# (WIP) GDB - Python Providers +# GDB - Python Providers Below are links to relevant parts of the GDB documentation diff --git a/src/doc/rustc-dev-guide/src/debuginfo/intro.md b/src/doc/rustc-dev-guide/src/debuginfo/intro.md index 0f1e59fa65e26..e8c4d11d12b0a 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/intro.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/intro.md @@ -1,13 +1,13 @@ -# Debug Info +# Debug info Debug info is a collection of information generated by the compiler that allows debuggers to -correctly interpret the state of a program while it is running. That includes things like mapping -instruction addresses to lines of code in the source file, and type layout information so that -bytes in memory can be read and displayed in a meaningful way. +correctly interpret the state of a program while it is running. +That includes things like mapping instruction addresses to lines of code in the source file, +and type layout information so that bytes in memory can be read and displayed in a meaningful way. Debug info can be a slightly overloaded term, covering all the layers between Rust MIR, and the -end-user seeing the output of their debugger onscreen. In brief, the stack from beginning to end is -as follows: +end-user seeing the output of their debugger onscreen. +In brief, the stack from beginning to end is as follows: 1. Rustc inspects the MIR and communicates the relevant source, symbol, and type information to LLVM 2. LLVM translates this information into a target-specific debug info format during compilation @@ -33,65 +33,84 @@ API layers (e.g. VSCode extension by way of the # DWARF -The is the primary debug info format for `*-gnu` targets. It is typically bundled in with the -binary, but it [can be generated as a separate file](https://gcc.gnu.org/wiki/DebugFission). The -DWARF standard is available [here](https://dwarfstd.org/). +The is the primary debug info format for `*-gnu` targets. +It is typically bundled in with the +binary, but it [can be generated as a separate file](https://gcc.gnu.org/wiki/DebugFission). +The DWARF standard is available [here](https://dwarfstd.org/). > NOTE: To inspect DWARF debug info, [gimli](https://crates.io/crates/gimli) can be used > programatically. If you prefer a GUI, the author recommends [DWEX](https://github.com/sevaa/dwex) # PDB/CodeView -The primary debug info format for `*-msvc` targets. PDB is a proprietary container format created by -Microsoft that, unfortunately, +The primary debug info format for `*-msvc` targets. +PDB is a proprietary container format created by Microsoft that, unfortunately, [has multiple meanings](https://docs.rs/ms-pdb/0.1.10/ms_pdb/taster/enum.Flavor.html). -We are concerned with ordinary PDB files, as Portable PDB is used mainly for .Net applications. PDB -files are separate from the compiled binary and use the `.pdb` extension. - -PDB files contain CodeView objects, equivalent to DWARF's tags. CodeView, the debugger that -consumed CodeView objects, was originally released in 1985. Its original intent was for C debugging, -and was later extended to support Visual C++. There are still minor alterations to the format to -support modern architectures and languages, but many of these changes are undocumented and/or -sparsely used. - -It is important to keep this context in mind when working with CodeView objects. Due to its origins, -the "feature-set" of these objects is very limited, and focused around the core features of C. It -does not have many of the convenience or features of modern DWARF standards. A fair number of -workarounds exist within the debug info stack to compensate for CodeView's shortcomings. - -Due to its proprietary nature, it is very difficult to find information about PDB and CodeView. Many -of the sources were made at vastly different times and contain incomplete or somewhat contradictory -information. As such this page will aim to collect as many sources as possible. - -* [CodeView 1.0 specification](./CodeView.pdf) +We are concerned with ordinary PDB files, as Portable PDB is used mainly for .Net applications. +PDB files are separate from the compiled binary and use the `.pdb` extension. + +PDB files contain CodeView objects, equivalent to DWARF's tags. +CodeView, the debugger that consumed CodeView objects, was originally released in 1985. +Its original intent was for C debugging, +and was later extended to support Visual C++. +There are still minor alterations to the format to support modern architectures and languages, +but many of these changes are undocumented and/or sparsely used. + +It is important to keep this context in mind when working with CodeView objects. +Due to its origins, +the "feature-set" of these objects is very limited, and focused around the core features of C. +It does not have many of the convenience or features of modern DWARF standards. +A fair number of workarounds exist within the debug info stack +to compensate for CodeView's shortcomings. + +Due to its proprietary nature, it is very difficult to find information about PDB and CodeView. +Many of the sources were made at vastly different times +and contain incomplete or somewhat contradictory information. +As such, this page will aim to collect as many sources as possible. + +* [TIS PE specification](https://web.archive.org/web/20260315080740/http://x-ways.net/winhex/kb/ff/PE_EXE.pdf) +which includes a lengthy section titled "Microsoft Symbol and Type Information", detailing much of +the CodeView format. +The document was created in 1993, but the information is still detailed, +accurate, and has useful diagrams. * LLVM * [CodeView Overview](https://llvm.org/docs/SourceLevelDebugging.html#codeview-debug-info-format) * [PDB Overview and technical details](https://llvm.org/docs/PDB/index.html) * Microsoft * [microsoft-pdb](https://github.com/microsoft/microsoft-pdb) - A C/C++ implementation of a PDB - reader. The implementation does not contain the full PDB or CodeView specification, but does - contain enough information for other PDB consumers to be written. At time of writing (Nov 2025), + reader. + The implementation does not contain the full PDB or CodeView specification, but does + contain enough information for other PDB consumers to be written. + At time of writing (Nov 2025), this repo has been archived for several years. * [pdb-rs](https://github.com/microsoft/pdb-rs/) - A Rust-based PDB reader and writer based on - other publicly-available information. Does not guarantee stability or spec compliance. Also - contains `pdbtool`, which can dump PDB files (`cargo install pdbtool`) + other publicly-available information. + Does not guarantee stability or spec compliance. + Also contains `pdbtool`, which can dump PDB files (`cargo install pdbtool`) * [Debug Interface Access SDK](https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/getting-started-debug-interface-access-sdk). While it does not document the PDB format directly, details can be gleaned from the interface itself. + * [PDB-Documentation](https://github.com/PascalBeyer/PDB-Documentation) - a resource compiling + much of the publicly available information about PDB and CodeView. # Debuggers -Rust supports 3 major debuggers: GDB, LLDB, and CDB. Each has its own set of requirements, -limitations, and quirks. This unfortunately creates a large surface area to account for. +Rust supports 3 major debuggers: GDB, LLDB, and CDB. +Each has its own set of requirements, +limitations, and quirks. +This unfortunately creates a large surface area to account for. -> NOTE: CDB is a proprietary debugger created by Microsoft. The underlying engine also powers ->WinDbg, KD, the Microsoft C/C++ extension for VSCode, and part of the Visual Studio Debugger. In ->these docs, it will be referred to as CDB for consistency +> NOTE: CDB is a proprietary debugger created by Microsoft. +> The underlying engine also powers WinDbg, KD, the Microsoft C/C++ extension for VSCode, +> and part of the Visual Studio Debugger. +> In these docs, it will be referred to as CDB for consistency While GDB and LLDB do offer facilities to natively support Rust's value layout, this isn't -completely necessary. Rust currently outputs debug info very similar to that of C++, allowing -debuggers without Rust support to work with a slightly degraded experience. More detail will be -included in later sections, but here is a quick reference for the capabilities of each debugger: +completely necessary. +Rust currently outputs debug info very similar to that of C++, allowing +debuggers without Rust support to work with a slightly degraded experience. +More detail will be included in later sections, +but here is a quick reference for the capabilities of each debugger: | Debugger | Debug Info Format | Native Rust support | Expression Style | Visualizer Scripts | | --- | --- | --- | --- | --- | @@ -108,7 +127,9 @@ Below, are several unsupported debuggers that are of particular note due to thei in the future. * [Bugstalker](https://github.com/godzie44/BugStalker) is an x86-64 Linux debugger written in Rust, -specifically to debug Rust programs. While promising, it is still in early development. -* [RAD Debugger](https://github.com/EpicGamesExt/raddebugger) is a Windows-only GUI debugger. It has -a custom debug info format that PDB is translated into. The project also includes a linker that can -generate their new debug info format during the linking phase. \ No newline at end of file + specifically to debug Rust programs. + While promising, it is still in early development. +* [RAD Debugger](https://github.com/EpicGamesExt/raddebugger) is a Windows-only GUI debugger. + It has a custom debug info format that PDB is translated into. + The project also includes a linker that can generate their new debug info format + during the linking phase. diff --git a/src/doc/rustc-dev-guide/src/debuginfo/lldb-internals.md b/src/doc/rustc-dev-guide/src/debuginfo/lldb-internals.md index e104f1d245327..98eb1da6e77eb 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/lldb-internals.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/lldb-internals.md @@ -1,7 +1,8 @@ -# LLDB Internals +# LLDB internals LLDB's debug info processing relies on a set of extensible interfaces largely defined in -[lldb/src/Plugins][lldb_plugins]. These are meant to allow third-party compiler developers to add +[lldb/src/Plugins][lldb_plugins]. +These are meant to allow third-party compiler developers to add language support that is loaded at run-time by LLDB, but at time of writing (Nov 2025) the public API has not been settled on, so plugins exist either in LLDB itself or in standalone forks of LLDB. @@ -16,27 +17,32 @@ Here are some existing implementations of LLDB's plugin API: * [CodeLLDB's former fork with support for Rust](https://archive.softwareheritage.org/browse/origin/directory/?branch=refs/heads/codelldb/16.x&origin_url=https://github.com/vadimcn/llvm-project&path=lldb/source/Plugins/TypeSystem/Rust×tamp=2023-09-11T04:55:10Z) * [A work in progress reimplementation of Rust support](https://github.com/Walnut356/llvm-project/tree/lldbrust/19.x) * [A Rust expression parser plugin](https://github.com/tromey/lldb/tree/a0fc10ce0dacb3038b7302fff9f6cb8cb34b37c6/source/Plugins/ExpressionParser/Rust). -This was written before the `TypeSystem` API was created. Due to the freeform nature of expression parsing, the +This was written before the `TypeSystem` API was created. +Due to the freeform nature of expression parsing, the underlyng lexing, parsing, function calling, etc. should still offer valuable insights. -## Rust Support and TypeSystemClang - -As mentioned in the debug info overview, LLDB has partial Rust support. To further clarify, Rust -uses the plugin-pipeline that was built for C/C++ (though it contains some helpers for Rust enum -types), which relies directly on the `clang` compiler's representation of types. This imposes heavy -restrictions on how much we can change when LLDB's output doesn't match what we want. Some -workarounds can help, but at the end of the day Rust's needs are secondary compared to making sure +## Rust support and TypeSystemClang + +As mentioned in the debug info overview, LLDB has partial Rust support. +To further clarify, +Rust uses the plugin-pipeline that was built for C/C++ +(though it contains some helpers for Rust enum types), +which relies directly on the `clang` compiler's representation of types. +This imposes heavy restrictions on how much we can change +when LLDB's output doesn't match what we want. +Some workarounds can help, but at the end of the day, +Rust's needs are secondary compared to making sure C and C++ compilation and debugging work correctly. -LLDB is receptive to adding a `TypeSystemRust`, but it is a massive undertaking. This section serves -to not only document how we currently interact with [`TypeSystemClang`][ts_clang], but also as light -guidance on implementing a `TypeSystemRust` in the future. +LLDB is receptive to adding a `TypeSystemRust`, but it is a massive undertaking. +This section serves to not only document how we currently interact with [`TypeSystemClang`], +but also as light guidance on implementing a `TypeSystemRust` in the future. -[ts_clang]: https://github.com/llvm/llvm-project/tree/main/lldb/source/Plugins/TypeSystem/Clang +[`TypeSystemClang`]: https://github.com/llvm/llvm-project/tree/main/lldb/source/Plugins/TypeSystem/Clang It is worth noting that a `TypeSystem` directly interacting with the target language's compiler is -the intention, but it is not a requirement. One can create all the necessary supporting types within -their plugin implementation. +the intention, but it is not a requirement. +One can create all the necessary supporting types within their plugin implementation. > Note: LLDB's documentation, including comments in the source code, is pretty sparse. Trying to > understand how language support works by reading `TypeSystemClang`'s implementation is somewhat @@ -47,8 +53,9 @@ their plugin implementation. ## DWARF vs PDB -LLDB is unique in being able to handle both DWARF and PDB debug information. This does come with -some added complexity. To complicate matters further, PDB support is split between `dia`, which +LLDB is unique in being able to handle both DWARF and PDB debug information. +This does come with some added complexity. +To complicate matters further, PDB support is split between `dia`, which relies on the `msdia140.dll` library distributed with Visual Studio, and `native`, which is written from scratch using publicly available information about the PDB format. @@ -63,50 +70,59 @@ from scratch using publicly available information about the PDB format. [dia_discourse]: https://discourse.llvm.org/t/rfc-removing-the-dia-pdb-plugin-from-lldb/87827 [dia_tracking]: https://github.com/llvm/llvm-project/issues/114906 -## Debug Node Parsing +## Debug node parsing -The first step is to process the raw debug nodes into something usable. This primarily occurs in -the [`DWARFASTParser`][dwarf_ast] and [`PdbAstBuilder`][pdb_ast] classes. These classes are fed a -deserialized form of the debug info generated from [`SymbolFileDWARF`][sf_dwarf] and -[`SymbolFileNativePDB`][sf_pdb] respectively. The `SymbolFile` implementers make almost no -transformations to the underlying debug info before passing it to the parsers. For both PDB and -DWARF, the debug info is read using LLVM's debug info handlers. +The first step is to process the raw debug nodes into something usable. +This primarily occurs in the [`DWARFASTParser`][dwarf_ast] and [`PdbAstBuilder`][pdb_ast] classes. +These classes are fed a deserialized form of the debug info +generated from [`SymbolFileDWARF`][sf_dwarf] and [`SymbolFileNativePDB`][sf_pdb] respectively. +The `SymbolFile` implementers make almost no +transformations to the underlying debug info before passing it to the parsers. +For both PDB and DWARF, the debug info is read using LLVM's debug info handlers. [dwarf_ast]: https://github.com/llvm/llvm-project/tree/main/lldb/source/Plugins/SymbolFile/DWARF [pdb_ast]: https://github.com/llvm/llvm-project/tree/main/lldb/source/Plugins/SymbolFile/NativePDB [sf_dwarf]: https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h [sf_pdb]: https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h -The parsers translate the nodes into more convenient formats for LLDB's purposes. For `clang`, these -formats are `clang::QualType`, `clang::Decl`, and `clang::DeclContext`, which are the types `clang` -uses internally when compiling C and C++. Again, using the compiler's representation of types is not a +The parsers translate the nodes into more convenient formats for LLDB's purposes. +For `clang`, these formats are `clang::QualType`, `clang::Decl`, and `clang::DeclContext`, +which are the types `clang` uses internally when compiling C and C++. +Again, using the compiler's representation of types is not a requirement, but the plugin system was built with it as a possibility. > Note: The above types will be referred to language-agnostically as `LangType`, `Decl`, and `DeclContext` when the specific implementation details of `TypeSystemClang` are not relevant. -`LangType` represents a type. This includes information such as the name of the type, the size and +`LangType` represents a type. +This includes information such as the name of the type, the size and alignment, its classification (e.g. struct, primitive, pointer), its qualifiers (e.g. `const`, `volatile`), template arguments, function argument and return types, etc. [Here][rust_type] is an example of what a `RustType` might look like. [rust_type]: https://github.com/Walnut356/llvm-project/blob/13bcfd502452606d69faeea76aec3a06db554af9/lldb/source/Plugins/TypeSystem/Rust/TypeSystemRust.h#L618 -`Decl` represents any kind of declaration. It could be a type, a variable, a static field of a +`Decl` represents any kind of declaration. +It could be a type, a variable, a static field of a struct, the value that a static or const is initialized with, etc. -`DeclContext` more or less represents a scope. `DeclContext`s typically contain `Decl`s and other -`DeclContexts`, though the relationship isn't that straight forward. For example, a function can be -both a `Decl` (because function signatures are types), **and** a `DeclContext` (because functions -contain variable declarations, nested functions declarations, etc.). +`DeclContext` more or less represents a scope. +`DeclContext`s typically contain `Decl`s and other +`DeclContexts`, though the relationship isn't that straight forward. +For example, a function can be both a `Decl` (because function signatures are types), +**and** a `DeclContext` +(because functions contain variable declarations, nested functions declarations, etc.). -The translation process can be quite verbose, but is usually straightforward. Much of the work here -is dependant on the exact information needed to fill out `LangType`, `Decl`, and `DeclContext`. +The translation process can be quite verbose, but is usually straightforward. +Much of the work here is dependant on the exact information needed to fill out `LangType`, +`Decl`, and `DeclContext`. Once a node is translated, a pointer to it is type-erased (`void*`) and wrapped in `CompilerType`, -`CompilerDecl`, or `CompilerDeclContext`. These wrappers associate the them with the `TypeSystem` -that owns them. Methods on these objects delegates to the `TypeSystem`, which casts the `void*` back -to the appropriate `LangType*`/`Decl*`/`DeclContext*` and operates on the internals. In Rust terms, +`CompilerDecl`, or `CompilerDeclContext`. +These wrappers associate the them with the `TypeSystem` that owns them. +Methods on these objects delegates to the `TypeSystem`, which casts the `void*` back +to the appropriate `LangType*`/`Decl*`/`DeclContext*` and operates on the internals. +In Rust terms, the relationship looks something like this: ```Rust @@ -135,59 +151,67 @@ impl TypeSystem for TypeSystemLang { } ``` -## Type Systems +## Type systems The [`TypeSystem` interface][ts_interface] has 3 major purposes: [ts_interface]: https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Symbol/TypeSystem.h#L69 -1. Act as the "sole authority" of a language's types. This allows the type system to be added to -LLDB's "pool" of type systems. When an executable is loaded, the target language is determined, and -the pool is queried to find a `TypeSystem` that claims it can handle the language. One can also use -the `TypeSystem` to retrieve the backing `SymbolFile`, search for types, and synthesize basic types -that might not exist in the debug info (e.g. primitives, arrays-of-`T`, pointers-to-`T`). +1. Act as the "sole authority" of a language's types. + This allows the type system to be added to LLDB's "pool" of type systems. + When an executable is loaded, the target language is determined, and + the pool is queried to find a `TypeSystem` that claims it can handle the language. + One can also use the `TypeSystem` to retrieve the backing `SymbolFile`, + search for types, and synthesize basic types + that might not exist in the debug info (e.g. primitives, arrays-of-`T`, pointers-to-`T`). 2. Manage the lifetimes of the `LangType`, `Decl`, and `DeclContext` objects 3. Customize the "defaults" of how those types appear and how they can be interacted with. The first two functions are pretty straightforward so we will focus on the third. Many of the functions in the `TypeSystem` interface will look familiar if you have worked with the -visualizer scripts. These functions underpin `SBType` the `SBValue` functions with matching names. +visualizer scripts. +These functions underpin `SBType` the `SBValue` functions with matching names. For example, `TypeSystem::GetFormat` returns the default format for the type if no custom formatter has been applied to it. -Of particular note are `GetIndexOfChildWithName` and `GetNumChildren`. The `TypeSystem` versions of -these functions operate on a *type*, not a value like the `SBValue` versions. The values returned -from the `TypeSystem` functions dictate what parts of the struct can be interacted with *at all* by -the rest of LLDB. If a field is ommitted, that field effectively no longer exists to LLDB. +Of particular note are `GetIndexOfChildWithName` and `GetNumChildren`. +The `TypeSystem` versions of these functions operate on a *type*, +not a value like the `SBValue` versions. +The values returned from the `TypeSystem` functions +dictate what parts of the struct can be interacted with *at all* by the rest of LLDB. +If a field is ommitted, that field effectively no longer exists to LLDB. Additionally, since they do not work with objects, there is no underlying memory to inspect or -interpret. Essentially, this means these functions do not have the same purpose as their equivalent -`SyntheticProvider` functions. There is no way to determine how many elements a `Vec` has or what -address those elements live at. It is also not possible to determine the value of the discriminant -of a sum-type. +interpret. +Essentially, this means these functions do not have the same purpose as their equivalent +`SyntheticProvider` functions. +There is no way to determine how many elements a `Vec` has or what address those elements live at. +It is also not possible to determine the value of the discriminant of a sum-type. Ideally, the `TypeSystem` should expose types as they appear in the debug info with as few -alterations as possible. LLDB's synthetics and frontend can handle making the type pretty. If some -piece of information is useless, the Rust compiler should be altered to not output that debug info -in the first place. +alterations as possible. +LLDB's synthetics and frontend can handle making the type pretty. +If some piece of information is useless, +the Rust compiler should be altered to not output that debug info in the first place. -## Expression Parsing +## Expression parsing -The `TypeSystem` is typically written to have a counterpart that can handle expression parsing. It -requires implementing a few extra functions in the `TypeSystem` interface. The bulk of the -expression parsing code should live in [lldb/source/Plugins/ExpressionParser][expr]. +The `TypeSystem` is typically written to have a counterpart that can handle expression parsing. +It requires implementing a few extra functions in the `TypeSystem` interface. +The bulk of the expression parsing code should live in [lldb/source/Plugins/ExpressionParser][expr]. [expr]: https://github.com/llvm/llvm-project/tree/main/lldb/source/Plugins/ExpressionParser -There isn't too much of note about the parser. It requires implementing a simple interpreter that -can handle (possibly simplified) Rust syntax. They operate on `lldb::ValueObject`s, which are the -objects that underpin `SBValue`. +There isn't too much of note about the parser. +It requires implementing a simple interpreter that can handle (possibly simplified) Rust syntax. +They operate on `lldb::ValueObject`s, which are the objects that underpin `SBValue`. ## Language -The [`Language` plugins][lang_plugin] are the C++ equivalent to the Python visualizer scripts. They -operate on `SBValue` objects for the same purpose: creating synthetic children and pretty-printing. +The [`Language` plugins][lang_plugin] are the C++ equivalent to the Python visualizer scripts. +They operate on `SBValue` objects for the same purpose: +creating synthetic children and pretty-printing. The [CPlusPlusLanguage's implementations][cpp_lang] for the LibCxx types are great resources to learn how visualizers should be written. @@ -200,9 +224,10 @@ their python equivalent. While debug node parsing, type systems, and expression parsing are all closely tied to eachother, the `Language` plugin is encapsulated more and thus can be written "standalone" for any language -that an existing type system supports. Due to the lower barrier of entry, a `RustLanguage` plugin +that an existing type system supports. +Due to the lower barrier of entry, a `RustLanguage` plugin may be a good stepping stone towards full language support in LLDB. ## Visualizers -WIP \ No newline at end of file +WIP diff --git a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md index 83e2b0d5794e8..58d4bd068f5bb 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md @@ -330,7 +330,7 @@ of the synthetic. By implementing an instance summary, we can retrieve the variant name via `self.variant.GetTypeName()` and some string manipulation. -# Writing Visualizer Scripts +# Writing visualizer scripts > IMPORTANT: Unlike GDB and CDB, LLDB can debug executables with either DWARF or PDB debug info. >Visualizers must be written to account for both formats whenever possible. See: @@ -373,7 +373,7 @@ use depending on what version of LLDB the script detects. This is vital for backwards compatibility once we begin using recognizer functions, as recognizers were added in lldb 19.0. -## Visualizer Resolution +## Visualizer resolution The order that visualizers resolve in is listed [here][formatters_101]. In short: diff --git a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md index cc052b6b965f1..4f5bdaa1e6795 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md @@ -1,7 +1,8 @@ -# (WIP) LLVM Codegen +# LLVM codegen When Rust calls an LLVM `DIBuilder` function, LLVM translates the given information to a -["debug record"][dbg_record] that is format-agnostic. These records can be inspected in the LLVM-IR. +["debug record"][dbg_record] that is format-agnostic. +These records can be inspected in the LLVM-IR. [dbg_record]: https://llvm.org/docs/SourceLevelDebugging.html#debug-records @@ -9,4 +10,4 @@ It is important to note that tags within the debug records are **always stored a the target calls for PDB debug info, during codegen the debug records will then be passed through [a module that translates the DWARF tags to their CodeView counterparts][cv]. -[cv]:https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp \ No newline at end of file +[cv]:https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp diff --git a/src/doc/rustc-dev-guide/src/debuginfo/natvis-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/natvis-visualizers.md index 653e7d5d65555..1b156465f4f85 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/natvis-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/natvis-visualizers.md @@ -1,3 +1,3 @@ -# (WIP) CDB - Natvis +# CDB - Natvis Official documentation for Natvis can be found [here](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects) and [here](https://code.visualstudio.com/docs/cpp/natvis) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/rust-codegen.md b/src/doc/rustc-dev-guide/src/debuginfo/rust-codegen.md index 73fa68d36076a..f879579de9907 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/rust-codegen.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/rust-codegen.md @@ -1,43 +1,46 @@ -# Rust Codegen +# Rust codegen The first phase in debug info generation requires Rust to inspect the MIR of the program and -communicate it to LLVM. This is primarily done in [`rustc_codegen_llvm/debuginfo`][llvm_di], though -some type-name processing exists in [`rustc_codegen_ssa/debuginfo`][ssa_di]. Rust communicates to -LLVM via the `DIBuilder` API - a thin wrapper around LLVM's internals that exists in -[rustc_llvm][rustc_llvm]. +communicate it to LLVM. +This is primarily done in [`rustc_codegen_llvm/debuginfo`][llvm_di], though +some type-name processing exists in [`rustc_codegen_ssa/debuginfo`][ssa_di]. +Rust communicates to LLVM via the `DIBuilder` API, +a thin wrapper around LLVM's internals that exists in [rustc_llvm]. [llvm_di]: https://github.com/rust-lang/rust/tree/main/compiler/rustc_codegen_llvm/src/debuginfo [ssa_di]: https://github.com/rust-lang/rust/tree/main/compiler/rustc_codegen_ssa/src/debuginfo [rustc_llvm]: https://github.com/rust-lang/rust/tree/main/compiler/rustc_llvm -# Type Information +# Type information Type information typically consists of the type name, size, alignment, as well as things like -fields, generic parameters, and storage modifiers if they are relevant. Much of this work happens in -[rustc_codegen_llvm/src/debuginfo/metadata][di_metadata]. +fields, generic parameters, and storage modifiers if they are relevant. +Much of this work happens in [rustc_codegen_llvm/src/debuginfo/metadata][di_metadata]. [di_metadata]: https://github.com/rust-lang/rust/blob/main/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs It is important to keep in mind that the goal is not necessarily "represent types exactly how they appear in Rust", rather it is to represent them in a way that allows debuggers to most accurately -reconstruct the data during debugging. This distinction is vital to understanding the core work that +reconstruct the data during debugging. +This distinction is vital to understanding the core work that occurs on this layer; many changes made here will be for the purpose of working around debugger limitations when no other option will work. ## Quirks -Rust's generated DI nodes "pretend" to be C/C++ for both CDB and LLDB's sake. This can result in -some unintuitive and non-idiomatic debug info. +Rust's generated DI nodes "pretend" to be C/C++ for both CDB and LLDB's sake. +This can result in some unintuitive and non-idiomatic debug info. -### Pointers and Reference +### Pointers and references Wide pointers/references/`Box` are treated as a struct with 2 fields: `data_ptr` and `length`. All non-wide pointers, references, and `Box` pointers are output as pointer nodes, and no -distinction is made between `mut` and non-`mut`. Several attempts have been made to rectify this, -but unfortunately there is not a straightforward solution. Using the `reference` DI nodes of the -respective formats has pitfalls. There is a semantic difference between C++ references and Rust -references that is unreconcilable. +distinction is made between `mut` and non-`mut`. +Several attempts have been made to rectify this, +but unfortunately there is not a straightforward solution. +Using the `reference` DI nodes of the respective formats has pitfalls. +There is a semantic difference between C++ references and Rust references that is unreconcilable. >From [cppreference](https://en.cppreference.com/w/cpp/language/reference.html): > @@ -48,24 +51,27 @@ references that is unreconcilable. > >Because references are not objects, **there are no arrays of references, no pointers to references, and no references to references** -The current proposed solution is to simply [typedef the pointer nodes][issue_144394]. +The current proposed solution is to simply [typedef the pointer nodes]. -[issue_144394]: https://github.com/rust-lang/rust/pull/144394 +[typedef the pointer nodes]: https://github.com/rust-lang/rust/pull/144394 Using the `const` qualifier to denote non-`mut` poses potential issues due to LLDB's internal optimizations. In short, LLDB attempts to cache the child-values of variables (e.g. struct fields, -array elements) when stepping through code. A heuristic is used to determine which values are safely -cache-able, and `const` is part of that heuristic. Research has not been done into how this would +array elements) when stepping through code. +A heuristic is used to determine which values are safely +cache-able, and `const` is part of that heuristic. +Research has not been done into how this would interact with things like Rust's interior mutability constructs. ### DWARF vs PDB While most of the type information is fairly straight forward, one notable issue is the debug info -format of the target. Each format has different semantics and limitations, as such they require -slightly different debug info in some cases. This is gated by calls to -[`cpp_like_debuginfo`][cpp_like]. +format of the target. +Each format has different semantics and limitations, as such they require +slightly different debug info in some cases. +This is gated by calls to [`cpp_like_debuginfo`]. -[cpp_like]: https://github.com/rust-lang/rust/blob/main/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs#L813 +[`cpp_like_debuginfo`]: https://github.com/rust-lang/rust/blob/main/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs#L813 ### Naming @@ -97,7 +103,8 @@ consecutive `>`'s with a space (`> >`) in type names. [^2]: While these type names are generated as part of the debug info node (which is then wrapped in a typedef node with the Rust name), once the LLVM-IR node is converted to a CodeView node, the type -name information is lost. This is because CodeView has special shorthand nodes for primitive types, +name information is lost. +This is because CodeView has special shorthand nodes for primitive types, and those shorthand nodes to not have a "name" field. ### Generics @@ -106,10 +113,11 @@ Rust outputs generic *type* information (`T` in `ArrayVec`), but no information (`N` in `ArrayVec`). CodeView does not have a leaf node for generics/C++ templates, so all generic information is lost -when generating PDB debug info. There are workarounds that allow the debugger to retrieve the -generic arguments via the type name, but it is fragile solution at best. Efforts are being made to -contact Microsoft to correct this deficiency, and/or to use one of the unused CodeView node types as -a suitable equivalent. +when generating PDB debug info. +There are workarounds that allow the debugger to retrieve the +generic arguments via the type name, but it is fragile solution at best. +Efforts are being made to contact Microsoft to correct this deficiency, +and/or to use one of the unused CodeView node types as a suitable equivalent. ### Type aliases @@ -126,9 +134,10 @@ Enum DI nodes are generated in [rustc_codegen_llvm/src/debuginfo/metadata/enums] #### DWARF -DWARF has a dedicated node for discriminated unions: `DW_TAG_variant`. It is a container that -references `DW_TAG_variant_part` nodes that may or may not contain a discriminant value. The -hierarchy looks as follows: +DWARF has a dedicated node for discriminated unions: `DW_TAG_variant`. +It is a container that references `DW_TAG_variant_part` nodes +that may or may not contain a discriminant value. +The hierarchy looks as follows: ```txt DW_TAG_structure_type (top-level type for the coroutine) @@ -175,9 +184,10 @@ union enum2$ { ``` An important note is that due to limitations in LLDB, the `DISCR_*` value generated is always a -`u64` even if the value is not `#[repr(u64)]`. This is largely a non-issue for LLDB because the +`u64` even if the value is not `#[repr(u64)]`. +This is largely a non-issue for LLDB because the `DISCR_*` value and the `tag` are read into `uint64_t` values regardless of their type. -# Source Information +# Source information -TODO \ No newline at end of file +TODO diff --git a/src/doc/rustc-dev-guide/src/debuginfo/testing.md b/src/doc/rustc-dev-guide/src/debuginfo/testing.md index f58050875e1a0..7aec83aa97ac6 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/testing.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/testing.md @@ -1,8 +1,8 @@ -# (WIP) Testing +# Testing The debug info test suite is undergoing a substantial rewrite. This section will be filled out as the rewrite makes progress. Please see [this tracking issue][148483] for more information. -[148483]: https://github.com/rust-lang/rust/issues/148483 \ No newline at end of file +[148483]: https://github.com/rust-lang/rust/issues/148483 diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 7ae1c881be8f7..1aca1b2eab1c5 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -34,6 +34,9 @@ to these tools should be filed against the tools directly in their respective up The exception is that when rustc changes are required to implement a new tool feature or test, that should happen in one collective rustc PR. +Similarly, if your rustc changes break the build of some subtree dependency, +you should include fixes for those in the rustc PR as well. + `subtree` dependencies are currently managed by two distinct approaches: * Using `git subtree` diff --git a/src/doc/rustc-dev-guide/src/hir-typeck/summary.md b/src/doc/rustc-dev-guide/src/hir-typeck/summary.md index 23df97a9cf833..5fd10663694c5 100644 --- a/src/doc/rustc-dev-guide/src/hir-typeck/summary.md +++ b/src/doc/rustc-dev-guide/src/hir-typeck/summary.md @@ -3,7 +3,7 @@ The [`hir_analysis`] crate contains the source for "type collection" as well as a bunch of related functionality. Checking the bodies of functions is implemented in the [`hir_typeck`] crate. -These crates draw heavily on the [type inference] and [trait solving]. +These crates draw heavily on [type inference] and [trait solving]. [`hir_analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html [`hir_typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/index.html @@ -14,8 +14,8 @@ These crates draw heavily on the [type inference] and [trait solving]. Type "collection" is the process of converting the types found in the HIR (`hir::Ty`), which represent the syntactic things that the user wrote, into the -**internal representation** used by the compiler (`Ty<'tcx>`) – we also do -similar conversions for where-clauses and other bits of the function signature. +**internal representation** used by the compiler (`Ty<'tcx>`). +Note that we also do similar conversions for where-clauses and other bits of the function signature. To try and get a sense of the difference, consider this function: @@ -25,9 +25,10 @@ fn foo(x: Foo, y: self::Foo) { ... } // ^^^ ^^^^^^^^^ ``` -Those two parameters `x` and `y` each have the same type: but they will have -distinct `hir::Ty` nodes. Those nodes will have different spans, and of course -they encode the path somewhat differently. But once they are "collected" into +Those two parameters `x` and `y` each have the same type, +but they will have distinct `hir::Ty` nodes. +Those nodes will have different spans, and of course they encode the path somewhat differently. +But once they are "collected" into `Ty<'tcx>` nodes, they will be represented by the exact same internal type. Collection is defined as a bundle of [queries] for computing information about @@ -35,8 +36,7 @@ the various functions, traits, and other items in the crate being compiled. Note that each of these queries is concerned with *interprocedural* things – for example, for a function definition, collection will figure out the type and signature of the function, but it will not visit the *body* of the function in -any way, nor examine type annotations on local variables (that's the job of -type *checking*). +any way, nor examine type annotations on local variables (that's the job of type *checking*). For more details, see the [`collect`][collect] module. diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md index 0a79d98c5db04..a8bc9a87d3b4c 100644 --- a/src/doc/rustc-dev-guide/src/normalization.md +++ b/src/doc/rustc-dev-guide/src/normalization.md @@ -1,4 +1,4 @@ -# Aliases and Normalization +# Aliases and normalization ## Aliases @@ -17,7 +17,7 @@ so this chapter mostly discusses things in the context of types (even though the [`TyKind::Alias`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/enum.TyKind.html#variant.Alias [`AliasTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/enum.AliasTyKind.html -### Rigid, Ambiguous and Unnormalized Aliases +### Rigid, ambiguous and unnormalized aliases Aliases can either be "rigid", "ambiguous", or simply unnormalized. @@ -68,7 +68,7 @@ only it just hasn't been done yet. It is worth noting that Free and Inherent aliases cannot be rigid or ambiguous as naming them also implies having resolved the definition of the alias, which specifies the underlying type of the alias. -### Diverging Aliases +### Diverging aliases An alias is considered to "diverge" if its definition does not specify an underlying non-alias type to normalize to. A concrete example of diverging aliases: @@ -126,11 +126,11 @@ fn main() { In this example, we only encounter an error from the diverging alias during codegen of `foo::<()>`. If the call to `foo` is removed, then no compilation error will be emitted. -### Opaque Types +### Opaque types Opaque types are a relatively special kind of alias, and are covered in [their own chapter](opaque-types-type-alias-impl-trait.md). -### Const Aliases +### Const aliases Unlike type aliases, const aliases are not represented directly in the type system. Instead, const aliases are always an anonymous body containing a path expression to a const item. @@ -157,7 +157,7 @@ fn bar() { This is likely to change as const generics functionality is improved. For example, `feature(associated_const_equality)` and `feature(min_generic_const_args)` both require handling const aliases similarly to types (without an anonymous constant wrapping all const args). -## What is Normalization +## What is normalization ### Structural vs deep normalization diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 802df2286095d..1ba30d86a6913 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -48,7 +48,7 @@ which is useful to keep peak memory in check. Having a THIR representation of all bodies of a crate in memory at the same time would be very heavy. -You can get a debug representation of the THIR by passing the `-Zunpretty=thir-tree` flag +You can get a debug representation of the THIR by passing the `-Zunpretty=thir-flat` flag to `rustc`. To demonstrate, let's use the following example: @@ -59,213 +59,168 @@ fn main() { } ``` -Here is how that gets represented in THIR (as of Aug 2022): +Here is how that gets represented in THIR (as of Jul 2026): ```rust,no_run +DefId(0:3 ~ main[26fd]::main): Thir { + body_type: Fn( + fn(), + ), + attributes: {}, // no match arms arms: [], + blocks: [ + Block { + targeted_by_break: false, + region_scope: Node(1), + span: main.rs:1:11: 3:2 (#0), + stmts: [ + s0, + ], + expr: None, + safety_mode: Safe, + }, + ], exprs: [ // expression 0, a literal with a value of 1 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:13: 2:14 (#0), kind: Literal { lit: Spanned { node: Int( - 1, + Pu128( + 1, + ), Unsuffixed, ), - span: oneplustwo.rs:2:13: 2:14 (#0), + span: main.rs:2:13: 2:14 (#0), }, neg: false, }, + ty: i32, + temp_scope_id: 4, + span: main.rs:2:13: 2:14 (#0), }, // expression 1, scope surrounding literal 1 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:13: 2:14 (#0), kind: Scope { + region_scope: Node(4), + hir_id: HirId(DefId(0:3 ~ main[26fd]::main).4), // reference to expression 0 above - region_scope: Node(3), - lint_level: Explicit( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 3, - }, - ), value: e0, }, + ty: i32, + temp_scope_id: 4, + span: main.rs:2:13: 2:14 (#0), }, // expression 2, literal 2 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:17: 2:18 (#0), kind: Literal { lit: Spanned { node: Int( - 2, + Pu128( + 2, + ), Unsuffixed, ), - span: oneplustwo.rs:2:17: 2:18 (#0), + span: main.rs:2:17: 2:18 (#0), }, neg: false, }, + ty: i32, + temp_scope_id: 5, + span: main.rs:2:17: 2:18 (#0), }, // expression 3, scope surrounding literal 2 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:17: 2:18 (#0), kind: Scope { - region_scope: Node(4), - lint_level: Explicit( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 4, - }, - ), - // reference to expression 2 above + region_scope: Node(5), + hir_id: HirId(DefId(0:3 ~ main[26fd]::main).5), + // reference to expression 0 above value: e2, }, + ty: i32, + temp_scope_id: 5, + span: main.rs:2:17: 2:18 (#0), }, // expression 4, represents 1 + 2 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:13: 2:18 (#0), kind: Binary { op: Add, // references to scopes surrounding literals above lhs: e1, rhs: e3, }, + ty: i32, + temp_scope_id: 3, + span: main.rs:2:13: 2:18 (#0), }, // expression 5, scope surrounding expression 4 Expr { - ty: i32, - temp_lifetime: Some( - Node(1), - ), - span: oneplustwo.rs:2:13: 2:18 (#0), kind: Scope { - region_scope: Node(5), - lint_level: Explicit( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 5, - }, - ), + region_scope: Node(3), + hir_id: HirId(DefId(0:3 ~ main[26fd]::main).3), value: e4, }, + ty: i32, + temp_scope_id: 3, + span: main.rs:2:13: 2:18 (#0), }, // expression 6, block around statement Expr { - ty: (), - temp_lifetime: Some( - Node(9), - ), - span: oneplustwo.rs:1:11: 3:2 (#0), kind: Block { - body: Block { - targeted_by_break: false, - region_scope: Node(8), - opt_destruction_scope: None, - span: oneplustwo.rs:1:11: 3:2 (#0), - // reference to statement 0 below - stmts: [ - s0, - ], - expr: None, - safety_mode: Safe, - }, + block: b0, }, + ty: (), + temp_scope_id: 8, + span: main.rs:1:11: 3:2 (#0), }, // expression 7, scope around block in expression 6 Expr { - ty: (), - temp_lifetime: Some( - Node(9), - ), - span: oneplustwo.rs:1:11: 3:2 (#0), kind: Scope { - region_scope: Node(9), - lint_level: Explicit( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 9, - }, - ), + region_scope: Node(8), + hir_id: HirId(DefId(0:3 ~ main[26fd]::main).8), value: e6, }, - }, - // destruction scope around expression 7 - Expr { ty: (), - temp_lifetime: Some( - Node(9), - ), - span: oneplustwo.rs:1:11: 3:2 (#0), - kind: Scope { - region_scope: Destruction(9), - lint_level: Inherited, - value: e7, - }, + temp_scope_id: 8, + span: main.rs:1:11: 3:2 (#0), }, ], stmts: [ - // let statement Stmt { kind: Let { - remainder_scope: Remainder { block: 8, first_statement_index: 0}, - init_scope: Node(1), + remainder_scope: Remainder { block: 1, first_statement_index: 0}, + init_scope: Node(2), pattern: Pat { ty: i32, - span: oneplustwo.rs:2:9: 2:10 (#0), + span: main.rs:2:9: 2:10 (#0), + extra: None, kind: Binding { - mutability: Not, name: "x", - mode: ByValue, + mode: BindingMode( + No, + Not, + ), var: LocalVarId( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 7, - }, + HirId(DefId(0:3 ~ main[26fd]::main).7), ), ty: i32, subpattern: None, is_primary: true, + is_shorthand: false, }, }, initializer: Some( e5, ), else_block: None, - lint_level: Explicit( - HirId { - owner: DefId(0:3 ~ oneplustwo[6932]::main), - local_id: 6, - }, - ), + hir_id: HirId(DefId(0:3 ~ main[26fd]::main).6), + span: main.rs:2:5: 2:18 (#0), }, - opt_destruction_scope: Some( - Destruction(1), - ), }, ], + params: [], } ``` diff --git a/src/doc/rustc-dev-guide/src/typing-parameter-envs.md b/src/doc/rustc-dev-guide/src/typing-parameter-envs.md index 45635ebfa15d6..db9f369d2659e 100644 --- a/src/doc/rustc-dev-guide/src/typing-parameter-envs.md +++ b/src/doc/rustc-dev-guide/src/typing-parameter-envs.md @@ -1,6 +1,6 @@ -# Typing/Parameter Environments +# Typing/Parameter environments -## Typing Environments +## Typing environments When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). @@ -14,7 +14,7 @@ whereas different `ParamEnv`s can be used on a per-goal basis. [ocx]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html [fnctxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html -## Parameter Environments +## Parameter environments ### What is a `ParamEnv` @@ -197,7 +197,7 @@ impl Other for T { // `foo`'s unnormalized `ParamEnv` would be: // `[T: Sized, U: Sized, U: Trait]` -fn foo(a: U) +fn foo(a: U) where U: Trait<::Bar>, { @@ -222,7 +222,7 @@ In the next-gen trait solver the requirement for all where clauses in the `Param [pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html [normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html -## Typing Modes +## Typing modes Depending on what context we are performing type system operations in, different behaviour may be required. diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md index 3f7d55063ca6a..67df4f0a9b07f 100644 --- a/src/doc/rustc/src/symbol-mangling/index.md +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -17,13 +17,16 @@ The [`#[export_name]`attribute][reference-export_name] can be used to specify th Items listed in an [`extern` block][reference-extern-block] use the identifier of the item without mangling to refer to the item. The [`#[link_name]` attribute][reference-link_name] can be used to change that name. - +### WebAssembly import modules + +On WebAssembly targets, foreign items in `extern` blocks can use the same import name without +conflicting when they use different [`#[link(wasm_import_module = "...")]`][reference-link-attribute] +values. [reference-no_mangle]: ../../reference/abi.html#the-no_mangle-attribute [reference-export_name]: ../../reference/abi.html#the-export_name-attribute [reference-link_name]: ../../reference/items/external-blocks.html#the-link_name-attribute +[reference-link-attribute]: ../../reference/items/external-blocks.html#the-link-attribute [reference-extern-block]: ../../reference/items/external-blocks.html ## Decoding diff --git a/src/doc/unstable-book/src/library-features/try-as-dyn.md b/src/doc/unstable-book/src/library-features/try-as-dyn.md new file mode 100644 index 0000000000000..81abde709c6dc --- /dev/null +++ b/src/doc/unstable-book/src/library-features/try-as-dyn.md @@ -0,0 +1,90 @@ +# `try_as_dyn` + +The tracking issue for this feature is: [#144361] + +[#144361]: https://github.com/rust-lang/rust/issues/144361 + +------------------------ + +The `try_as_dyn` feature allows going from a generic `T` with no bounds +to a `dyn Trait`, if `T: Trait` and various conditions are upheld. It is +very related to specialization, as it allows you to specialize within +function bodies, but in a more general manner than `Any::downcast`. + +```rust +#![feature(try_as_dyn)] + +fn downcast_debug_format(t: &T) -> String { + match std::any::try_as_dyn::<_, dyn std::fmt::Debug>(t) { + Some(d) => format!("{d:?}"), + None => "default".to_string() + } +} +``` + + +## Rules and reasons for them + +> [!IMPORTANT] +> The main problem of **`try_as_dyn` and specialization is the compiler's inability, while trait-checking, to distinguish/_discriminate_ between any two given lifetimes**[^1]. + +[^1]: the compiler cannot _branch_ on whether "`'a : 'b` holds": for soundness, it can either choose not to know the answer, or _assume_ that it holds and produce an obligation for the borrow-checker which shall "assert this" (making compilation fail in a fatal manner if not). Most usages of Rust lie in the latter category (typical `where` clauses anywhere), whilst specialization/`try_as_dyn()` wants to support fallibility of the operation (_i.e._, being queried on a type not fulfilling the predicate without causing a compilation error). This rules out the latter, resulting in the need for the former, _i.e._, for the `try_as_dyn()` attempt to unconditionally "fail" with `None`. + +### `'static` is not mentioned anywhere in the `impl` block header. + +The most obvious one: if you have `impl IsStatic for &'static str`, then determining whether `&'? str : IsStatic` does hold amounts to discriminating `'? : 'static`. + +### Each outlives `where` bound (`Type: 'a` and `'a: 'b`) does not mention lifetime-infected parameters. + +Parameters are considered lifetime-infected if they are defined in an `impl` block's generic parameter list. +Const generics are excempt, as they can't affect lifetimes. +`for<'a>` lifetimes (and in the future types) are not lifetime-infected. + +We can create lifetime discrimination this way. For instance, given `impl<'a, 'b> Outlives<'a> for &'b str where 'b : 'a {}`, `Outlives<'static>` amounts to `IsStatic` from previous bullet. + +### Each lifetime-infected parameter is mentioned at most once in the `Self` type and the implemented trait's generic parameters, combined. + +Repetition of a parameter entails equality of those two use-sites; in lifetime-terms, this would be a double `'a : 'b` / `'b : 'a` clause, for instance. +Follow-up from the previous example: `impl<'a> Uses<'a> for &'a str {}`, and check whether `&'? str : Uses<'static>`. + +### Each individual trait where bound (`Type: Trait`) mentions each lifetime-infected parameter at most once. + +Mentioning a lifetime-infected parameter in multiple `where` bounds is allowed. + +Looking at the previous rules, which focuses on `Self : …`, this is just observing that shifting the requirements to other parameters within `where` clauses \[ought to\] boil down to the same set of issues. + +This is _unnecessarily restrictive_: we should be able to loosen it up somehow. Repetition only in `where` clauses seems fine. + + +### The `impl` block is a handwritten impl + +as opposed to a type implementing a trait automatically by the compiler (such as auto-traits, `dyn Bounds… : Bounds…`, and closures) + + +The reason for this is that some such auto-generated impls _come with hidden bounds or whatnot_, which run afoul of the previous rules, whilst also being _extremely challenging for the current compiler logic to know of such bounds_. +IIUC, this restriction could be lifted in the future should the compiler logic be better at spotting these hidden bounds, when present. + +One contrived such example being the case of `dyn 'u + for<'a> Outlives<'a>`, where the compiler-generated `impl` for it of `Outlives` is: `impl<'b, 'u> Outlives<'b> for dyn 'u + for<'a> Outlives<'a> where 'b : 'u {}` which violates the "`'a: 'b` not to mention lt-infected params" rule, whilst also being hard to detect in current compiler logic. + +### Associated type projections (`::Assoc`) are not mentioned anywhere in the `impl` block header. + +Associated-type equality bounds can very much amount to lifetime-infected parameter equality constraints, +which are problematic as per the "at most one mention of each lifetime-infected parameter in header" rule. +To illustrate, with the following definitions, `&'? str: Trait<'static>` discriminates `'?` against `'static`: +```rust +trait Trait<'x> {} +impl<'a, 'b> Trait<'b> for &'a str +where + // &'a str = &'b str, + Option<&'a str>: IntoIterator, +{} +``` + +```rust +trait Trait<'x> {} +impl<'a> Trait<'a> for &'a str {} +``` + +### Each trait `where` bound with an associated type equality (`Type: Trait`) does not mention lifetime-infected parameters. + +Checking whether `Option<&'? str>: IntoIterator` holds discriminates `'?` against `'static`. diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 5f49bbf0c7e31..65c83a612bf9f 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -11,6 +11,7 @@ extern crate rustc_ast_pretty; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_expand; +extern crate rustc_feature; extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index 099a644282102..baa1a86ad25c8 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -16,7 +16,7 @@ use crate::parse::parser::{ Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError, }; use crate::parse::session::ParseSess; -use crate::utils::{contains_skip, mk_sp}; +use crate::utils::{contains_custom_attributes, contains_skip, mk_sp}; mod visitor; @@ -472,6 +472,16 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { } Err(e) => match e { ModError::FileNotFound(_, default_path, _secondary_path) => { + if contains_custom_attributes(attrs) { + // It's possible that at least one of the attributes is a custom proc macro + // that takes the module tokens as an input. It's hard to know for sure + // since rustfmt only operates on the AST pre-expansion. In this case we'll + // be overly permissive and just ignore the file not found error so rustfmt + // can still try formatting the input. + tracing::warn!("Couldn't find file for mod {};`", mod_name.to_string()); + return Ok(None); + } + Err(ModuleResolutionError { module: mod_name.to_string(), kind: ModuleResolutionErrorKind::NotFound { file: default_path }, diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 15a4fce93482a..131455fc0ff12 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -6,6 +6,7 @@ use rustc_ast::ast::{ NodeId, Path, RestrictionKind, Visibility, VisibilityKind, }; use rustc_ast_pretty::pprust; +use rustc_feature::is_builtin_attr_name; use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; @@ -327,6 +328,13 @@ pub(crate) fn contains_skip(attrs: &[Attribute]) -> bool { .any(|a| a.meta().map_or(false, |a| is_skip(&a))) } +#[inline] +pub(crate) fn contains_custom_attributes(attrs: &[Attribute]) -> bool { + attrs + .iter() + .any(|a| a.name().is_some_and(|name| !is_builtin_attr_name(name))) +} + #[inline] pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { // Never try to insert semicolons on expressions when we're inside diff --git a/src/tools/rustfmt/tests/target/issue_6959.rs b/src/tools/rustfmt/tests/target/issue_6959.rs new file mode 100644 index 0000000000000..2194ba3285353 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue_6959.rs @@ -0,0 +1,2 @@ +#[my_macro] +mod foo; diff --git a/tests/assembly-llvm/asm/aarch64-types.rs b/tests/assembly-llvm/asm/aarch64-types.rs index 21f9294dc647b..c171ba3b11e13 100644 --- a/tests/assembly-llvm/asm/aarch64-types.rs +++ b/tests/assembly-llvm/asm/aarch64-types.rs @@ -1,8 +1,10 @@ //@ add-minicore -//@ revisions: aarch64 arm64ec +//@ revisions: aarch64 aarch64_be arm64ec //@ assembly-output: emit-asm //@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64_be] compile-flags: --target aarch64_be-unknown-linux-gnu +//@ [aarch64_be] needs-llvm-components: aarch64 //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec] needs-llvm-components: aarch64 //@ compile-flags: -Zmerge-functions=disabled diff --git a/tests/assembly-llvm/cmse-clear-padding.rs b/tests/assembly-llvm/cmse-clear-padding.rs index b092bf304dcca..93b10845ea511 100644 --- a/tests/assembly-llvm/cmse-clear-padding.rs +++ b/tests/assembly-llvm/cmse-clear-padding.rs @@ -123,6 +123,8 @@ struct WideU8 { a: u8, } +// `extern "C"` does not clear the padding. +// // CHECK-LABEL: c_ret_with_wide_u8: // CHECK: mov r7, sp // CHECK-NEXT: orr.w r0, r0, r1, lsl #16 @@ -131,6 +133,8 @@ extern "C" fn c_ret_with_wide_u8(a: u8, b: u8) -> [WideU8; 2] { [WideU8 { a }, WideU8 { a: b }] } +// Upper bits are cleared by uxtb. +// // CHECK-LABEL: cmse_ret_with_wide_u8: // CHECK: mov r7, sp // CHECK-NEXT: uxtb r1, r1 @@ -141,6 +145,36 @@ extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8(a: u8, b: u8) -> [WideU8; [WideU8 { a }, WideU8 { a: b }] } +// Same idea, the padding is recognized even through the MaybeUninit. +// +// CHECK-LABEL: cmse_ret_with_wide_u8_uninit: +// CHECK: mov r7, sp +// CHECK-NEXT: uxtb r0, r0 +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +// CHECK-NEXT: bic r0, r0, #-16711936 +#[no_mangle] +extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit( + a: u16, + b: u16, +) -> [MaybeUninit; 2] { + unsafe { [mem::transmute(a), mem::transmute(b)] } +} + +// Same idea, the padding is recognized even through the MaybeUninit. +// +// CHECK-LABEL: cmse_ret_with_wide_u8_uninit_tuple: +// CHECK: mov r7, sp +// CHECK-NEXT: uxtb r0, r0 +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +// CHECK-NEXT: bic r0, r0, #-16711936 +#[no_mangle] +extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit_tuple( + a: u16, + b: u16, +) -> (MaybeUninit, MaybeUninit) { + unsafe { (mem::transmute(a), mem::transmute(b)) } +} + // CHECK-LABEL: c_call_with_inner_wide_u8: // CHECK: push {r7, lr} // CHECK-NEXT: .setfp r7, sp @@ -177,28 +211,230 @@ extern "C" fn cmse_call_with_inner_wide_u8( unsafe { f(x) } } -// CHECK-LABEL: cmse_ret_with_wide_u8_uninit: +/// No variant-dependent padding. +#[repr(C)] +enum VariantsSameSize { + A(u16), + B(u16), +} +impl Copy for VariantsSameSize {} + +// CHECK-LABEL: variants_same_size: // CHECK: mov r7, sp -// CHECK-NEXT: uxtb r0, r0 +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] // CHECK-NEXT: orr.w r0, r0, r1, lsl #16 -// CHECK-NEXT: bic r0, r0, #-16711936 #[no_mangle] -extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit( - a: u16, - b: u16, -) -> [MaybeUninit; 2] { - unsafe { [mem::transmute(a), mem::transmute(b)] } +extern "cmse-nonsecure-entry" fn variants_same_size(v: &VariantsSameSize) -> VariantsSameSize { + *v } -// CHECK-LABEL: cmse_ret_with_wide_u8_uninit_tuple: +/// One byte of variant-dependent padding. +#[repr(C)] +enum VariantsDifferentSize { + A(u8), + B(u16), +} +impl Copy for VariantsDifferentSize {} + +// A uxtbeq conditionally clears the padding only for variant A. +// +// CHECK-LABEL: variants_different_size: // CHECK: mov r7, sp -// CHECK-NEXT: uxtb r0, r0 +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] +// CHECK-NEXT: lsls r2, r0, #31 +// CHECK-NEXT: it eq +// CHECK-NEXT: uxtbeq r1, r1 // CHECK-NEXT: orr.w r0, r0, r1, lsl #16 -// CHECK-NEXT: bic r0, r0, #-16711936 #[no_mangle] -extern "cmse-nonsecure-entry" fn cmse_ret_with_wide_u8_uninit_tuple( - a: u16, - b: u16, -) -> (MaybeUninit, MaybeUninit) { - unsafe { (mem::transmute(a), mem::transmute(b)) } +extern "cmse-nonsecure-entry" fn variants_different_size( + v: &VariantsDifferentSize, +) -> VariantsDifferentSize { + *v +} + +enum Void {} +impl Copy for Void {} + +#[repr(C)] +enum UninhabitedVariant { + A(Void), + B(u16), +} +impl Copy for UninhabitedVariant {} + +// Only `B` is inhabited, so reading the tag is not needed. +// +// CHECK-LABEL: uninhabited_variant: +// CHECK: mov r7, sp +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +#[no_mangle] +extern "cmse-nonsecure-entry" fn uninhabited_variant(v: &UninhabitedVariant) -> UninhabitedVariant { + *v +} + +// The single guaranteed-padding byte is cleared with a `bic` mask over the whole loaded word. +// CHECK-LABEL: variants_same_size_array: +// CHECK: mov r7, sp +// CHECK-NEXT: ldr r0, [r0] +// CHECK-NEXT: bic r0, r0, #65280 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "cmse-nonsecure-entry" fn variants_same_size_array( + v: &[VariantsSameSize; 1], +) -> [VariantsSameSize; 1] { + *v +} + +// CHECK-LABEL: variants_different_size_array: +// CHECK: mov r7, sp +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] +// CHECK-NEXT: lsls r2, r0, #31 +// CHECK-NEXT: it eq +// CHECK-NEXT: uxtbeq r1, r1 +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "cmse-nonsecure-entry" fn variants_different_size_array( + v: &[VariantsDifferentSize; 1], +) -> [VariantsDifferentSize; 1] { + *v +} + +// CHECK-LABEL: variants_same_size_tuple: +// CHECK: mov r7, sp +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "cmse-nonsecure-entry" fn variants_same_size_tuple( + v: &(VariantsSameSize,), +) -> (VariantsSameSize,) { + *v +} + +// CHECK-LABEL: variants_different_size_tuple: +// CHECK: mov r7, sp +// CHECK-NEXT: ldrh r1, [r0, #2] +// CHECK-NEXT: ldrb r0, [r0] +// CHECK-NEXT: lsls r2, r0, #31 +// CHECK-NEXT: it eq +// CHECK-NEXT: uxtbeq r1, r1 +// CHECK-NEXT: orr.w r0, r0, r1, lsl #16 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "cmse-nonsecure-entry" fn variants_different_size_tuple( + v: &(VariantsDifferentSize,), +) -> (VariantsDifferentSize,) { + *v +} + +/// Three variants of different sizes. +#[repr(C)] +enum ThreeVariants { + A(u8), + B(u16), + C(u32), +} + +// CHECK-LABEL: cmse_call_three_variants: +// CHECK: mov r3, r0 +// +// Clears padding in the extend the discriminant. +// CHECK-NEXT: uxtb r0, r1 +// +// Uses uxtb for the A variant, uxtheq for the B variant, +// and nothing for the C variant. +// +// CHECK-NEXT: cbz r0, .LBB{{[0-9_]+}} +// CHECK-NEXT: cmp r0, #1 +// CHECK-NEXT: it eq +// CHECK-NEXT: uxtheq r2, r2 +// CHECK-NEXT: b .LBB{{[0-9_]+}} +// CHECK-NEXT: .LBB{{[0-9_]+}}: +// CHECK-NEXT: uxtb r2, r2 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "C" fn cmse_call_three_variants( + f: unsafe extern "cmse-nonsecure-call" fn(ThreeVariants), + x: ThreeVariants, +) { + unsafe { f(x) } +} + +/// Three variants of different sizes, with a nested enum. +#[repr(C)] +enum ThreeVariantsNested { + A(u8), + B(Option), + C(u32), +} + +// CHECK-LABEL: cmse_call_three_variants_nested: +// CHECK: mov r3, r0 +// +// Clears padding in the extend the discriminant. +// CHECK-NEXT: uxtb r0, r1 +// +// Match on the discriminant, jump to A block +// +// CHECK-NEXT: cbz r0, .LBB{{[0-9_]+}} +// +// Match on the discriminant, do nothing for C. +// +// CHECK-NEXT: cmp r0, #1 +// CHECK-NEXT: bne .LBB{{[0-9_]+}} +// +// The B variant conditionally clears the Option payload. +// +// CHECK-NEXT: lsls r1, r2, #31 +// CHECK-NEXT: movw r1, #65535 +// CHECK-NEXT: it eq +// CHECK-NEXT: moveq r1, #254 +// CHECK-NEXT: ands r2, r1 +// CHECK-NEXT: b .LBB{{[0-9_]+}} +// +// The A variant uses uxtb. +// +// CHECK-NEXT: .LBB{{[0-9_]+}}: +// CHECK-NEXT: uxtb r2, r2 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "C" fn cmse_call_three_variants_nested( + f: unsafe extern "cmse-nonsecure-call" fn(ThreeVariantsNested), + x: ThreeVariantsNested, +) { + unsafe { f(x) } +} + +/// The tag is stored in the niche of the `bool`. +#[repr(C)] +struct BoolU32 { + flag: bool, + val: u32, +} + +// Bit 0b0010 is used to encode the tag, so `r0 - 2 == 0` checks the tag value. +// Zero-extension clears padding in the tag 32-bit word, the `val` is either 0 +// (stored in r1) when None or the actual value r2 when Some. +// +// CHECK-LABEL: cmse_call_niche: +// CHECK: mov r7, sp +// CHECK-NEXT: mov r3, r0 +// CHECK-NEXT: uxtb r0, r1 +// CHECK-NEXT: subs r1, r0, #2 +// CHECK-NEXT: it ne +// CHECK-NEXT: movne r1, r2 +#[no_mangle] +#[expect(improper_ctypes_definitions)] +extern "C" fn cmse_call_niche( + f: unsafe extern "cmse-nonsecure-call" fn(Option), + x: Option, +) { + unsafe { f(x) } } diff --git a/tests/codegen-llvm/preserve-vec-element-types.rs b/tests/codegen-llvm/preserve-vec-element-types.rs index 50e560412e817..b3908b1c24cc2 100644 --- a/tests/codegen-llvm/preserve-vec-element-types.rs +++ b/tests/codegen-llvm/preserve-vec-element-types.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@ add-minicore -#![feature(no_core, repr_simd, f16, f128)] +#![feature(no_core, f16, f128)] #![crate_type = "lib"] #![no_std] #![no_core] @@ -12,11 +12,9 @@ // useful for optimization. It prevents additional bitcasts that make LLVM patterns fail. extern crate minicore; +use minicore::simd::Simd; use minicore::*; -#[repr(simd)] -pub struct Simd([T; N]); - #[repr(C)] struct Pair(T, T); diff --git a/tests/codegen-llvm/regparm-inreg.rs b/tests/codegen-llvm/regparm-inreg.rs index ef70f7f8be0bd..77d4c206071e7 100644 --- a/tests/codegen-llvm/regparm-inreg.rs +++ b/tests/codegen-llvm/regparm-inreg.rs @@ -14,12 +14,13 @@ #![crate_type = "lib"] #![no_core] -#![feature(no_core, lang_items, repr_simd)] +#![feature(no_core, lang_items)] extern crate minicore; -use minicore::*; pub mod tests { + use minicore::simd::Simd; + // regparm doesn't work for "fastcall" calling conv (only 2 inregs) // CHECK: @f1(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3) #[no_mangle] @@ -98,8 +99,7 @@ pub mod tests { pub extern "C" fn f10(_: f32, _: f64, _: bool, _: i16) {} #[allow(non_camel_case_types)] - #[repr(simd)] - pub struct __m128([f32; 4]); + type __m128 = Simd; // regparm0: @f11(i32 noundef %_1, <4 x float> %_2, i32 noundef %_3, i32 noundef %_4) // regparm1: @f11(i32 inreg noundef %_1, <4 x float> %_2, i32 noundef %_3, i32 noundef %_4) @@ -111,8 +111,7 @@ pub mod tests { pub extern "C" fn f11(_: i32, _: __m128, _: i32, _: i32) {} #[allow(non_camel_case_types)] - #[repr(simd)] - pub struct __m256([f32; 8]); + type __m256 = Simd; // regparm0: @f12(i32 noundef %_1, <8 x float> %_2, i32 noundef %_3, i32 noundef %_4) // regparm1: @f12(i32 inreg noundef %_1, <8 x float> %_2, i32 noundef %_3, i32 noundef %_4) diff --git a/tests/codegen-llvm/s390x-simd.rs b/tests/codegen-llvm/s390x-simd.rs index 8439e79716746..f223f6edad3df 100644 --- a/tests/codegen-llvm/s390x-simd.rs +++ b/tests/codegen-llvm/s390x-simd.rs @@ -6,35 +6,13 @@ #![crate_type = "rlib"] #![feature(no_core, asm_experimental_arch)] -#![feature(simd_ffi, intrinsics, repr_simd)] +#![feature(simd_ffi, intrinsics)] #![no_core] extern crate minicore; +use minicore::simd::*; use minicore::*; -#[repr(simd)] -struct i8x16([i8; 16]); - -#[repr(simd)] -struct i16x8([i16; 8]); - -#[repr(simd)] -struct i32x4([i32; 4]); - -#[repr(simd)] -struct i64x2([i64; 2]); - -#[repr(simd)] -struct f32x4([f32; 4]); - -#[repr(simd)] -struct f64x2([f64; 2]); - -impl Copy for i8x16 {} -impl Copy for i16x8 {} -impl Copy for i32x4 {} -impl Copy for i64x2 {} - #[rustc_intrinsic] unsafe fn simd_ge(x: T, y: T) -> U; diff --git a/tests/mir-opt/early_otherwise_branch.dont_hoist_deref.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.dont_hoist_deref.EarlyOtherwiseBranch.diff new file mode 100644 index 0000000000000..66891f818a6cf --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.dont_hoist_deref.EarlyOtherwiseBranch.diff @@ -0,0 +1,38 @@ +- // MIR for `dont_hoist_deref` before EarlyOtherwiseBranch ++ // MIR for `dont_hoist_deref` after EarlyOtherwiseBranch + + fn dont_hoist_deref(_1: u64, _2: *const u64) -> u64 { + let mut _0: u64; + + bb0: { + switchInt(copy _1) -> [1: bb1, 2: bb2, otherwise: bb5]; + } + + bb1: { + switchInt(copy (*_2)) -> [1: bb3, otherwise: bb5]; + } + + bb2: { + switchInt(copy (*_2)) -> [2: bb4, otherwise: bb5]; + } + + bb3: { + _0 = const 100_u64; + goto -> bb6; + } + + bb4: { + _0 = const 200_u64; + goto -> bb6; + } + + bb5: { + _0 = const 999_u64; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs index 19a5d25de2dfb..54406f41f8fc1 100644 --- a/tests/mir-opt/early_otherwise_branch.rs +++ b/tests/mir-opt/early_otherwise_branch.rs @@ -156,6 +156,56 @@ fn target_self(val: i32) { } } +// EMIT_MIR early_otherwise_branch.dont_hoist_deref.EarlyOtherwiseBranch.diff +#[custom_mir(dialect = "runtime")] +fn dont_hoist_deref(q: u64, p: *const u64) -> u64 { + // The dereference of `p` cannot be hoisted because the `otherwise` branch + // can be taken without dereferencing `p`. + // Hoisting the dereference could therefore cause UB when `p` is null. + // Hoisting a dereference also requires proving that the dereference is safe to reorder. + // CHECK-LABEL: fn dont_hoist_deref( + // CHECK: bb0: { + // CHECK-NEXT: switchInt(copy _1) + // CHECK: switchInt(copy (*_2)) + // CHECK: switchInt(copy (*_2)) + mir! { + { + match q { + 1 => bb1, + 2 => bb2, + _ => bb5, + } + } + bb1 = { + match *p { + 1 => bb3, + _ => bb5, + } + } + bb2 = { + match *p { + 2 => bb4, + _ => bb5, + } + } + bb3 = { + RET = 100; + Goto(bb6) + } + bb4 = { + RET = 200; + Goto(bb6) + } + bb5 = { + RET = 999; + Goto(bb6) + } + bb6 = { + Return() + } + } +} + fn main() { opt1(None, Some(0)); opt2(None, Some(0)); @@ -164,4 +214,5 @@ fn main() { opt5(0, 0); opt5_failed(0, 0); target_self(1); + dont_hoist_deref(3, std::ptr::null()); } diff --git a/tests/ui/abi/arm-unadjusted-intrinsic.rs b/tests/ui/abi/arm-unadjusted-intrinsic.rs index 1f386308c878f..788c5e67904ab 100644 --- a/tests/ui/abi/arm-unadjusted-intrinsic.rs +++ b/tests/ui/abi/arm-unadjusted-intrinsic.rs @@ -7,23 +7,19 @@ //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: aarch64 //@ ignore-backends: gcc -#![feature( - no_core, lang_items, link_llvm_intrinsics, - abi_unadjusted, repr_simd, arm_target_feature, -)] +#![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted, arm_target_feature)] #![no_std] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types)] extern crate minicore; +use minicore::simd::Simd; use minicore::*; // Regression test for https://github.com/rust-lang/rust/issues/118124. -#[repr(simd)] -pub struct int8x16_t(pub(crate) [i8; 16]); -impl Copy for int8x16_t {} +pub type int8x16_t = Simd; #[repr(C)] pub struct int8x16x4_t(pub int8x16_t, pub int8x16_t, pub int8x16_t, pub int8x16_t); diff --git a/tests/ui/abi/simd-abi-checks-empty-list.rs b/tests/ui/abi/simd-abi-checks-empty-list.rs index 8907a2c391db6..52e588b028bd2 100644 --- a/tests/ui/abi/simd-abi-checks-empty-list.rs +++ b/tests/ui/abi/simd-abi-checks-empty-list.rs @@ -6,14 +6,11 @@ //@ build-fail //@ ignore-backends: gcc #![no_core] -#![feature(no_core, repr_simd)] -#![allow(improper_ctypes_definitions)] +#![feature(no_core)] extern crate minicore; -use minicore::*; +use minicore::simd::Simd; -#[repr(simd)] -pub struct SimdVec([i32; 4]); - -pub extern "C" fn pass_by_vec(_: SimdVec) {} -//~^ ERROR: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI +#[expect(improper_ctypes_definitions)] +pub extern "C" fn pass_by_vec(_: Simd) {} +//~^ ERROR: this function definition uses SIMD vector type `Simd` which is not currently supported with the chosen ABI diff --git a/tests/ui/abi/simd-abi-checks-empty-list.stderr b/tests/ui/abi/simd-abi-checks-empty-list.stderr index 603f5daeb2a10..e19c775eee750 100644 --- a/tests/ui/abi/simd-abi-checks-empty-list.stderr +++ b/tests/ui/abi/simd-abi-checks-empty-list.stderr @@ -1,8 +1,8 @@ -error: this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI - --> $DIR/simd-abi-checks-empty-list.rs:18:1 +error: this function definition uses SIMD vector type `Simd` which is not currently supported with the chosen ABI + --> $DIR/simd-abi-checks-empty-list.rs:15:1 | -LL | pub extern "C" fn pass_by_vec(_: SimdVec) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here +LL | pub extern "C" fn pass_by_vec(_: Simd) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here error: aborting due to 1 previous error diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index c8f4483650ccd..8ca3d2f457899 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -12,29 +12,21 @@ //[z13_soft_float]~? WARN must be disabled to ensure that the ABI of the current target can be implemented correctly //[z13_soft_float]~? WARN target feature `soft-float` cannot be enabled with `-Ctarget-feature` -#![feature(no_core, repr_simd)] +#![feature(no_core)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types, improper_ctypes_definitions)] extern crate minicore; +use minicore::simd::*; use minicore::*; -#[repr(simd)] -pub struct i8x8([i8; 8]); -#[repr(simd)] -pub struct i8x16([i8; 16]); -#[repr(simd)] -pub struct i8x32([i8; 32]); #[repr(C)] pub struct Wrapper(T); +impl Copy for Wrapper {} + #[repr(transparent)] pub struct TransparentWrapper(T); - -impl Copy for i8x8 {} -impl Copy for i8x16 {} -impl Copy for i8x32 {} -impl Copy for Wrapper {} impl Copy for TransparentWrapper {} #[no_mangle] diff --git a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr index 0a40658fa66bf..c401da52ba878 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr @@ -1,21 +1,21 @@ -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:41:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:33:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:38:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:92:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:84:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -24,8 +24,8 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:91:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -34,48 +34,48 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:114:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:106:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:119:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:111:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:130:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:135:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:127:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:146:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:138:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:151:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:143:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr index 0a40658fa66bf..c401da52ba878 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr @@ -1,21 +1,21 @@ -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:41:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:33:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:38:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:92:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:84:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -24,8 +24,8 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:91:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -34,48 +34,48 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:114:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:106:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:119:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:111:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:130:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:135:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:127:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:146:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:138:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:151:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:143:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr index cda51a211324e..59697d6af254a 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr @@ -8,24 +8,24 @@ warning: target feature `soft-float` must be disabled to ensure that the ABI of = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:41:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:33:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:46:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:38:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:92:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:84:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -34,8 +34,8 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:99:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:91:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -44,48 +44,48 @@ LL | | ) -> TransparentWrapper { | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:114:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:106:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:119:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:111:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:130:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:122:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:135:1 +error: this function definition uses SIMD vector type `Wrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:127:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:146:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:138:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:151:1 +error: this function definition uses SIMD vector type `TransparentWrapper>` which (with the chosen ABI) requires the `vector` target feature, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:143:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here diff --git a/tests/ui/abi/simd-abi-checks-sse.rs b/tests/ui/abi/simd-abi-checks-sse.rs index b9c1c10757d14..736f32afcd464 100644 --- a/tests/ui/abi/simd-abi-checks-sse.rs +++ b/tests/ui/abi/simd-abi-checks-sse.rs @@ -6,17 +6,14 @@ //@ build-fail //@ needs-llvm-components: x86 //@ ignore-backends: gcc -#![feature(no_core, repr_simd)] +#![feature(no_core)] #![no_core] #![allow(improper_ctypes_definitions)] extern crate minicore; -use minicore::*; - -#[repr(simd)] -pub struct SseVector([i64; 2]); +use minicore::simd::Simd; #[no_mangle] -pub unsafe extern "C" fn f(_: SseVector) { - //~^ ERROR: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled +pub unsafe extern "C" fn f(_: Simd) { + //~^ ERROR: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `sse` target feature, which is not enabled } diff --git a/tests/ui/abi/simd-abi-checks-sse.stderr b/tests/ui/abi/simd-abi-checks-sse.stderr index 018d8b687d513..1a6583a511e0c 100644 --- a/tests/ui/abi/simd-abi-checks-sse.stderr +++ b/tests/ui/abi/simd-abi-checks-sse.stderr @@ -1,8 +1,8 @@ -error: this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled - --> $DIR/simd-abi-checks-sse.rs:20:1 +error: this function definition uses SIMD vector type `Simd` which (with the chosen ABI) requires the `sse` target feature, which is not enabled + --> $DIR/simd-abi-checks-sse.rs:17:1 | -LL | pub unsafe extern "C" fn f(_: SseVector) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here +LL | pub unsafe extern "C" fn f(_: Simd) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) diff --git a/tests/ui/any/any_static.next.stderr b/tests/ui/any/any_static.next.stderr new file mode 100644 index 0000000000000..e57d544140980 --- /dev/null +++ b/tests/ui/any/any_static.next.stderr @@ -0,0 +1,16 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/any_static.rs:18:35 + | +LL | fn extend(a: &Payload) -> &'static Payload { + | - - let's call the lifetime of this reference `'1` + | | + | `a` is a reference that is only valid in the function body +LL | let b: &(dyn Any + 'static) = try_as_dyn::<&Payload, dyn Any + 'static>(&a).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `a` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/any/any_static.old.stderr b/tests/ui/any/any_static.old.stderr new file mode 100644 index 0000000000000..e57d544140980 --- /dev/null +++ b/tests/ui/any/any_static.old.stderr @@ -0,0 +1,16 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/any_static.rs:18:35 + | +LL | fn extend(a: &Payload) -> &'static Payload { + | - - let's call the lifetime of this reference `'1` + | | + | `a` is a reference that is only valid in the function body +LL | let b: &(dyn Any + 'static) = try_as_dyn::<&Payload, dyn Any + 'static>(&a).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `a` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/any/any_static.rs b/tests/ui/any/any_static.rs new file mode 100644 index 0000000000000..7305cabfa8c16 --- /dev/null +++ b/tests/ui/any/any_static.rs @@ -0,0 +1,22 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(try_as_dyn)] + +use std::any::{Any, try_as_dyn}; + +type Payload = Box; + +fn main() { + let storage: Box = Box::new(Box::new(1i32)); + let wrong: &'static Payload = extend(&*storage); + drop(storage); + println!("{wrong}"); +} + +fn extend(a: &Payload) -> &'static Payload { + let b: &(dyn Any + 'static) = try_as_dyn::<&Payload, dyn Any + 'static>(&a).unwrap(); + //~^ ERROR: borrowed data escapes outside of function + let c: &&'static Payload = b.downcast_ref::<&'static Payload>().unwrap(); + *c +} diff --git a/tests/ui/any/builtin_bound.rs b/tests/ui/any/builtin_bound.rs new file mode 100644 index 0000000000000..8c4bcf7ad2e3f --- /dev/null +++ b/tests/ui/any/builtin_bound.rs @@ -0,0 +1,23 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass +#![feature(try_as_dyn)] + +trait Trait {} + +// In contrast to `T: Sized`, `Struct: Sized` does not go +// through a fast path, and is thus rejected by the builtin impl +// check that rejects all builtin impls in reflection mode. +// FIXME(try_as_dyn): should probably allow builtin impls that +// are never lifetime dependent (like Sized). +impl Trait for Struct where Struct: Sized {} + +struct Struct(T); + +const _: () = { + let x = Struct(42); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&x).is_none()); +}; + +fn main() {} diff --git a/tests/ui/any/hrtb.next.stderr b/tests/ui/any/hrtb.next.stderr new file mode 100644 index 0000000000000..385b3c3cf2212 --- /dev/null +++ b/tests/ui/any/hrtb.next.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/hrtb.rs:15:25 + | +LL | let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/hrtb.old.stderr b/tests/ui/any/hrtb.old.stderr new file mode 100644 index 0000000000000..385b3c3cf2212 --- /dev/null +++ b/tests/ui/any/hrtb.old.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/hrtb.rs:15:25 + | +LL | let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/hrtb.rs b/tests/ui/any/hrtb.rs new file mode 100644 index 0000000000000..ab31529a0d207 --- /dev/null +++ b/tests/ui/any/hrtb.rs @@ -0,0 +1,19 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +trait Foo<'a, 'b> {} + +trait Bar {} +impl Foo<'a, 'b> + ?Sized> Bar for Option<*const T> {} + +const _: () = { + let x: Option<*const dyn for<'a> Foo<'a, 'a>> = None; + let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + //~^ ERROR: `Option::unwrap()` on a `None` value +}; + +fn main() {} diff --git a/tests/ui/any/hrtb2.next.stderr b/tests/ui/any/hrtb2.next.stderr new file mode 100644 index 0000000000000..dfe000dc503a8 --- /dev/null +++ b/tests/ui/any/hrtb2.next.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/hrtb2.rs:15:25 + | +LL | let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/hrtb2.old.stderr b/tests/ui/any/hrtb2.old.stderr new file mode 100644 index 0000000000000..dfe000dc503a8 --- /dev/null +++ b/tests/ui/any/hrtb2.old.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/hrtb2.rs:15:25 + | +LL | let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/hrtb2.rs b/tests/ui/any/hrtb2.rs new file mode 100644 index 0000000000000..ee1bd7cde8982 --- /dev/null +++ b/tests/ui/any/hrtb2.rs @@ -0,0 +1,19 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +trait Foo<'a> {} + +trait Bar {} +impl Bar for Option<*const T> where T: for<'a> Foo<'a> {} + +const _: () = { + let x: Option<*const dyn Foo<'_>> = None; + let _dy: &dyn Bar = try_as_dyn(&x).unwrap(); + //~^ ERROR: `Option::unwrap()` on a `None` value +}; + +fn main() {} diff --git a/tests/ui/any/non_static.rs b/tests/ui/any/non_static.rs new file mode 100644 index 0000000000000..40d7bb7bf5469 --- /dev/null +++ b/tests/ui/any/non_static.rs @@ -0,0 +1,89 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@check-pass +#![feature(try_as_dyn)] + +trait Trait {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&42_i32).is_none()); +}; + +impl<'a> Trait for &'a [(); 1] {} +const _: () = { + let x = (); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&[x]).is_some()); +}; + +type Foo = &'static [(); 2]; + +// Ensure type aliases don't skip these checks +impl Trait for Foo {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&[(), ()]).is_none()); +}; + +impl Trait for &() {} +const _: () = { + let x = (); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&x).is_some()); +}; + +impl Trait for () {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&()).is_some()); +}; + +// Not fully generic impl -> returns None even tho +// implemented for *some* lifetimes +impl<'a> Trait for (&'a (), &'a ()) {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&(&(), &())).is_none()); +}; + +// Not fully generic impl -> returns None even tho +// implemented for *some* lifetimes +impl<'a, 'b: 'a> Trait for (&'a (), &'b (), ()) {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&(&(), &(), ())).is_none()); +}; + +// Only valid for 'static lifetimes -> returns None +// even though we are actually using a `'static` lifetime. +// We can't know what lifetimes are there during codegen, so +// we pessimistically assume it could be a shorter one +impl Trait for &'static u32 {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&42_u32).is_none()); +}; + +trait Trait2 {} + +struct Struct(T); + +// While this is the impl for `Trait`, in `Reflection` solver mode +// we reject the impl for `Trait2` below, and thus this impl also +// doesn't match. +impl Trait for Struct {} + +impl Trait2 for &'static u32 {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&Struct(&42_u32)).is_none()); +}; + +const _: () = { + trait Homo {} + impl Homo for (T, T) {} + + // Let's pick `T = &'_ i32`. + assert!(std::any::try_as_dyn::<_, dyn Homo>(&(&42_i32, &27_i32)).is_none()); +}; + +trait Trait3<'a> {} + +impl Trait3<'static> for () {} +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait3<'_>>(&()).is_none()); +}; + +fn main() {} diff --git a/tests/ui/any/reject_manual_impl.rs b/tests/ui/any/reject_manual_impl.rs new file mode 100644 index 0000000000000..590cebd48950f --- /dev/null +++ b/tests/ui/any/reject_manual_impl.rs @@ -0,0 +1,29 @@ +#![feature(try_as_dyn)] + +use std::any::TryAsDynCompatible; + +struct Foo(dyn Iterator); + +impl TryAsDynCompatible<'static> for Foo {} +//~^ ERROR: explicit impls for the `TryAsDynCompatible` trait are not permitted + +struct Bar(dyn Iterator); + +impl<'a> TryAsDynCompatible<'a> for Bar {} +//~^ ERROR: explicit impls for the `TryAsDynCompatible` trait are not permitted + +struct Baz; + +impl<'a> TryAsDynCompatible<'a> for Baz {} +//~^ ERROR: explicit impls for the `TryAsDynCompatible` trait are not permitted + +trait Trait {} + +impl<'a> TryAsDynCompatible<'a> for dyn Trait {} +//~^ ERROR: explicit impls for the `TryAsDynCompatible` trait are not permitted + +impl TryAsDynCompatible<'static> for dyn Iterator {} +//~^ ERROR: explicit impls for the `TryAsDynCompatible` trait are not permitted +//~| ERROR: only traits defined in the current crate can be implemented for arbitrary types + +fn main() {} diff --git a/tests/ui/any/reject_manual_impl.stderr b/tests/ui/any/reject_manual_impl.stderr new file mode 100644 index 0000000000000..37be37c47ea79 --- /dev/null +++ b/tests/ui/any/reject_manual_impl.stderr @@ -0,0 +1,46 @@ +error[E0322]: explicit impls for the `TryAsDynCompatible` trait are not permitted + --> $DIR/reject_manual_impl.rs:7:1 + | +LL | impl TryAsDynCompatible<'static> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `TryAsDynCompatible` not allowed + +error[E0322]: explicit impls for the `TryAsDynCompatible` trait are not permitted + --> $DIR/reject_manual_impl.rs:12:1 + | +LL | impl<'a> TryAsDynCompatible<'a> for Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `TryAsDynCompatible` not allowed + +error[E0322]: explicit impls for the `TryAsDynCompatible` trait are not permitted + --> $DIR/reject_manual_impl.rs:17:1 + | +LL | impl<'a> TryAsDynCompatible<'a> for Baz {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `TryAsDynCompatible` not allowed + +error[E0322]: explicit impls for the `TryAsDynCompatible` trait are not permitted + --> $DIR/reject_manual_impl.rs:22:1 + | +LL | impl<'a> TryAsDynCompatible<'a> for dyn Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `TryAsDynCompatible` not allowed + +error[E0322]: explicit impls for the `TryAsDynCompatible` trait are not permitted + --> $DIR/reject_manual_impl.rs:25:1 + | +LL | impl TryAsDynCompatible<'static> for dyn Iterator {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `TryAsDynCompatible` not allowed + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/reject_manual_impl.rs:25:1 + | +LL | impl TryAsDynCompatible<'static> for dyn Iterator {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------ + | | + | `dyn Iterator` is not defined in the current crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0117, E0322. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/any/static_method_bound.rs b/tests/ui/any/static_method_bound.rs new file mode 100644 index 0000000000000..b2cc77e4d9cfe --- /dev/null +++ b/tests/ui/any/static_method_bound.rs @@ -0,0 +1,33 @@ +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +type Payload = Box; + +trait Trait { + fn as_static(&self) -> &'static Payload + where + Self: 'static; +} + +impl<'a> Trait for &'a Payload { + fn as_static(&self) -> &'static Payload + where + Self: 'static, + { + *self + } +} + +fn main() { + let storage: Box = Box::new(Box::new(1i32)); + let wrong: &'static Payload = extend(&*storage); + drop(storage); + println!("{wrong}"); +} + +fn extend(a: &Payload) -> &'static Payload { + let b: &(dyn Trait + 'static) = try_as_dyn::<&Payload, dyn Trait + 'static>(&a).unwrap(); + //~^ ERROR: borrowed data escapes outside of function + b.as_static() +} diff --git a/tests/ui/any/static_method_bound.stderr b/tests/ui/any/static_method_bound.stderr new file mode 100644 index 0000000000000..152672d024ab1 --- /dev/null +++ b/tests/ui/any/static_method_bound.stderr @@ -0,0 +1,16 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/static_method_bound.rs:30:37 + | +LL | fn extend(a: &Payload) -> &'static Payload { + | - - let's call the lifetime of this reference `'1` + | | + | `a` is a reference that is only valid in the function body +LL | let b: &(dyn Trait + 'static) = try_as_dyn::<&Payload, dyn Trait + 'static>(&a).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `a` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/any/trait_info_of.next.stderr b/tests/ui/any/trait_info_of.next.stderr new file mode 100644 index 0000000000000..45bbbe4892937 --- /dev/null +++ b/tests/ui/any/trait_info_of.next.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `dyn Trait>: TryAsDynCompatible<'_>` is not satisfied + --> $DIR/trait_info_of.rs:30:30 + | +LL | .trait_info_of::>() + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `TryAsDynCompatible<'_>` is not implemented for `dyn Trait>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `TypeId::trait_info_of` + --> $SRC_DIR/core/src/any.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/any/trait_info_of.old.stderr b/tests/ui/any/trait_info_of.old.stderr new file mode 100644 index 0000000000000..45bbbe4892937 --- /dev/null +++ b/tests/ui/any/trait_info_of.old.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `dyn Trait>: TryAsDynCompatible<'_>` is not satisfied + --> $DIR/trait_info_of.rs:30:30 + | +LL | .trait_info_of::>() + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `TryAsDynCompatible<'_>` is not implemented for `dyn Trait>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `TypeId::trait_info_of` + --> $SRC_DIR/core/src/any.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/any/trait_info_of.rs b/tests/ui/any/trait_info_of.rs new file mode 100644 index 0000000000000..5eb6742be506e --- /dev/null +++ b/tests/ui/any/trait_info_of.rs @@ -0,0 +1,45 @@ +//! Check that we can't use `TypeId::trait_info_of` to unsoundly skip +//! the try_as_dyn checks. + +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +#![feature(type_info, ptr_metadata, arbitrary_self_types_pointers)] + +use std::any::TypeId; +use std::ptr::{self, DynMetadata}; + +type Payload = Box; + +trait Trait { + type Assoc; + fn method(self: *const Self, value: Self::Assoc) -> &'static Payload; +} +struct Thing; +impl Trait for Thing { + type Assoc = &'static Payload; + fn method(self: *const Self, value: Self::Assoc) -> &'static Payload { + value + } +} + +fn extend<'a>(payload: &'a Payload) -> &'static Payload { + let metadata: DynMetadata> = const { + TypeId::of::() + .trait_info_of::>() + //~^ ERROR `dyn Trait>: TryAsDynCompatible<'_>` is not satisfied + .unwrap() + .get_vtable() + }; + let ptr: *const dyn Trait = + ptr::from_raw_parts(std::ptr::null::<()>(), metadata); + ptr.method(payload) +} + +fn main() { + let payload: Box = Box::new(Box::new(1i32)); + let wrong: &'static Payload = extend(&*payload); + drop(payload); + println!("{wrong}"); +} diff --git a/tests/ui/any/try_as_dyn.rs b/tests/ui/any/try_as_dyn.rs index ee220f797ced9..cf9ca7bd885da 100644 --- a/tests/ui/any/try_as_dyn.rs +++ b/tests/ui/any/try_as_dyn.rs @@ -1,3 +1,6 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ run-pass #![feature(try_as_dyn)] @@ -7,7 +10,7 @@ use std::fmt::Debug; fn debug_format_with_try_as_dyn(t: &T) -> String { match std::any::try_as_dyn::<_, dyn Debug>(t) { Some(d) => format!("{d:?}"), - None => "default".to_string() + None => "default".to_string(), } } @@ -16,7 +19,7 @@ fn main() { #[allow(dead_code)] #[derive(Debug)] struct A { - index: usize + index: usize, } let a = A { index: 42 }; let result = debug_format_with_try_as_dyn(&a); diff --git a/tests/ui/any/try_as_dyn_assoc_ty_lifetime.rs b/tests/ui/any/try_as_dyn_assoc_ty_lifetime.rs new file mode 100644 index 0000000000000..aa2056a7fc42c --- /dev/null +++ b/tests/ui/any/try_as_dyn_assoc_ty_lifetime.rs @@ -0,0 +1,27 @@ +//@check-pass +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +trait HasAssoc<'a> { + type Assoc; +} +struct Dummy; +impl<'a> HasAssoc<'a> for Dummy { + // Changing this to &'a i64 makes try_as_dyn succeed + type Assoc = &'static i64; +} + +trait Trait {} +impl Trait for i32 where for<'a> Dummy: HasAssoc<'a, Assoc = &'a i64> {} + +const _: () = { + let x = 1i32; + assert!(try_as_dyn::<_, dyn Trait>(&x).is_none()); +}; + +fn main() {} diff --git a/tests/ui/any/try_as_dyn_builtin_impl.rs b/tests/ui/any/try_as_dyn_builtin_impl.rs new file mode 100644 index 0000000000000..4ed06a78c2e36 --- /dev/null +++ b/tests/ui/any/try_as_dyn_builtin_impl.rs @@ -0,0 +1,48 @@ +#![feature(try_as_dyn)] +//@ run-fail +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +use std::any::{Any, try_as_dyn}; + +type Payload = Box; + +trait Outlives<'b>: 'b {} + +trait WithLt { + type Ref; +} +impl<'a> WithLt for dyn for<'b> Outlives<'b> + 'a { + type Ref = &'a Payload; +} + +struct Thing(T::Ref); + +trait Trait { + fn get(&self) -> &'static Payload; +} +impl Trait for Thing +where + T: WithLt + for<'b> Outlives<'b> + ?Sized, +{ + fn get(&self) -> &'static Payload { + let x: &::Ref = &self.0; + let y: &(dyn Any + 'static) = x; + let z: &&'static Payload = y.downcast_ref().unwrap(); + *z + } +} + +fn extend<'a>(payload: &'a Payload) -> &'static Payload { + let thing: Thing Outlives<'b> + 'a> = Thing(payload); + let dy: &dyn Trait = try_as_dyn(&thing).unwrap(); + dy.get() +} + +fn main() { + let payload: Box = Box::new(Box::new(1)); + let wrong: &'static Payload = extend(&*payload); + drop(payload); + println!("{wrong}"); +} diff --git a/tests/ui/any/try_as_dyn_elaborated_bounds.rs b/tests/ui/any/try_as_dyn_elaborated_bounds.rs new file mode 100644 index 0000000000000..b0357e4fcca2c --- /dev/null +++ b/tests/ui/any/try_as_dyn_elaborated_bounds.rs @@ -0,0 +1,29 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@check-pass + +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +trait Trait: 'static {} +trait Other {} +struct Foo(T); + +impl Trait for () {} +impl Trait for &'static () {} + +// This impl has an implied `T: 'static` bound, but that's +// not an issue, as we just ignore all `Trait` impls where +// that would be a relevant distinguisher. +impl Other for Foo {} + +const _: () = { + let foo = Foo(()); + assert!(try_as_dyn::, dyn Other>(&foo).is_some()); + let foo = Foo(&()); + assert!(try_as_dyn::, dyn Other>(&foo).is_none()); +}; + +fn main() {} diff --git a/tests/ui/any/try_as_dyn_generic_impl.rs b/tests/ui/any/try_as_dyn_generic_impl.rs new file mode 100644 index 0000000000000..21033312fe277 --- /dev/null +++ b/tests/ui/any/try_as_dyn_generic_impl.rs @@ -0,0 +1,40 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(try_as_dyn)] +//@ check-pass + +use std::any::try_as_dyn; + +struct Thing(T); +trait Trait {} +impl Trait for Thing {} + +const _: () = { + let thing = Thing(1); + assert!(try_as_dyn::<_, dyn Trait>(&thing).is_some()); +}; + +struct Thing2(T); +impl Trait for Thing2 {} +struct NoDebug; + +const _: () = { + let thing = Thing2(1); + assert!(try_as_dyn::<_, dyn Trait>(&thing).is_some()); + let thing = Thing2(NoDebug); + assert!(try_as_dyn::<_, dyn Trait>(&thing).is_none()); +}; + +trait Trait2 {} +impl<'a, 'b> Trait2 for &'a &'b () {} + +struct Thing3(T); +impl Trait for Thing3 {} + +const _: () = { + let thing = Thing3(&&()); + assert!(try_as_dyn::<_, dyn Trait2>(&thing).is_none()); +}; + +fn main() {} diff --git a/tests/ui/any/try_as_dyn_generic_trait.next.stderr b/tests/ui/any/try_as_dyn_generic_trait.next.stderr new file mode 100644 index 0000000000000..99382f9a4032c --- /dev/null +++ b/tests/ui/any/try_as_dyn_generic_trait.next.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/try_as_dyn_generic_trait.rs:22:51 + | +LL | let convert: &dyn Convert<&'static Payload> = try_as_dyn(&payload).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/try_as_dyn_generic_trait.old.stderr b/tests/ui/any/try_as_dyn_generic_trait.old.stderr new file mode 100644 index 0000000000000..99382f9a4032c --- /dev/null +++ b/tests/ui/any/try_as_dyn_generic_trait.old.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: called `Option::unwrap()` on a `None` value + --> $DIR/try_as_dyn_generic_trait.rs:22:51 + | +LL | let convert: &dyn Convert<&'static Payload> = try_as_dyn(&payload).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/any/try_as_dyn_generic_trait.rs b/tests/ui/any/try_as_dyn_generic_trait.rs new file mode 100644 index 0000000000000..630c071218fc8 --- /dev/null +++ b/tests/ui/any/try_as_dyn_generic_trait.rs @@ -0,0 +1,26 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(try_as_dyn)] + +use std::any::try_as_dyn; + +type Payload = *const i32; + +trait Convert { + fn convert(&self) -> &T; +} + +impl Convert for T { + fn convert(&self) -> &T { + self + } +} + +const _: () = { + let payload: Payload = std::ptr::null(); + let convert: &dyn Convert<&'static Payload> = try_as_dyn(&payload).unwrap(); + //~^ ERROR: `Option::unwrap()` on a `None` value +}; + +fn main() {} diff --git a/tests/ui/any/try_as_dyn_mut.rs b/tests/ui/any/try_as_dyn_mut.rs index ff7baa32ea874..a4fadb72d2823 100644 --- a/tests/ui/any/try_as_dyn_mut.rs +++ b/tests/ui/any/try_as_dyn_mut.rs @@ -1,3 +1,6 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ run-pass #![feature(try_as_dyn)] @@ -7,7 +10,7 @@ use std::fmt::{Error, Write}; fn try_as_dyn_mut_write(t: &mut T, s: &str) -> Result<(), Error> { match std::any::try_as_dyn_mut::<_, dyn Write>(t) { Some(w) => w.write_str(s), - None => Ok(()) + None => Ok(()), } } diff --git a/tests/ui/any/try_as_dyn_soundness_test1.rs b/tests/ui/any/try_as_dyn_soundness_test1.rs index 0772e9a2d77ee..4dfb5492e3a59 100644 --- a/tests/ui/any/try_as_dyn_soundness_test1.rs +++ b/tests/ui/any/try_as_dyn_soundness_test1.rs @@ -1,19 +1,16 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ run-pass #![feature(try_as_dyn)] use std::any::try_as_dyn; -trait Trait { +trait Trait {} -} - -impl Trait for for<'a> fn(&'a Box) { - -} - -fn store(_: &'static Box) { +impl Trait for for<'a> fn(&'a Box) {} -} +fn store(_: &'static Box) {} fn main() { let fn_ptr: fn(&'static Box) = store; diff --git a/tests/ui/any/try_as_dyn_soundness_test2.rs b/tests/ui/any/try_as_dyn_soundness_test2.rs index c16b50d0261ed..a9985384cd1e6 100644 --- a/tests/ui/any/try_as_dyn_soundness_test2.rs +++ b/tests/ui/any/try_as_dyn_soundness_test2.rs @@ -1,14 +1,13 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ run-pass #![feature(try_as_dyn)] use std::any::try_as_dyn; -trait Trait { +trait Trait {} -} - -impl Trait fn(&'a Box)> for () { - -} +impl Trait fn(&'a Box)> for () {} fn main() { let dt = try_as_dyn::<_, dyn Trait)>>(&()); diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index c7373780e382c..d6317e32bd8fb 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -1,131 +1,131 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:139:18 + --> $DIR/bad-reg.rs:131:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:142:18 + --> $DIR/bad-reg.rs:134:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:145:26 + --> $DIR/bad-reg.rs:137:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:148:26 + --> $DIR/bad-reg.rs:140:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:152:18 + --> $DIR/bad-reg.rs:144:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:155:18 + --> $DIR/bad-reg.rs:147:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:158:26 + --> $DIR/bad-reg.rs:150:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:161:26 + --> $DIR/bad-reg.rs:153:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:165:18 + --> $DIR/bad-reg.rs:157:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:168:18 + --> $DIR/bad-reg.rs:160:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:171:26 + --> $DIR/bad-reg.rs:163:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:174:26 + --> $DIR/bad-reg.rs:166:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:178:18 + --> $DIR/bad-reg.rs:170:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:181:18 + --> $DIR/bad-reg.rs:173:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:184:26 + --> $DIR/bad-reg.rs:176:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:187:26 + --> $DIR/bad-reg.rs:179:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:183:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:185:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:187:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:189:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:199:31 + --> $DIR/bad-reg.rs:191:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:201:31 + --> $DIR/bad-reg.rs:193:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:203:31 + --> $DIR/bad-reg.rs:195:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:205:31 + --> $DIR/bad-reg.rs:197:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:200:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:202:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:204:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:206:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:208:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:210:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:220:31 + --> $DIR/bad-reg.rs:212:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:222:31 + --> $DIR/bad-reg.rs:214:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:224:31 + --> $DIR/bad-reg.rs:216:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:226:31 + --> $DIR/bad-reg.rs:218:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:220:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:222:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:224:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:226:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:228:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:230:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:232:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:234:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:236:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:238:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:240:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:242:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:264:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:266:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:268:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:270:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:264:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:266:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:268:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:270:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:272:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:274:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:276:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:278:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:280:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:282:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:284:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:286:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:328:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:330:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:332:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:334:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,19 +701,19 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:340:26 + --> $DIR/bad-reg.rs:332:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:65:27 + --> $DIR/bad-reg.rs:58:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -721,7 +721,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:68:28 + --> $DIR/bad-reg.rs:61:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -729,7 +729,7 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:76:35 + --> $DIR/bad-reg.rs:69:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -737,7 +737,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:28 + --> $DIR/bad-reg.rs:98:28 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -745,7 +745,7 @@ LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:109:29 + --> $DIR/bad-reg.rs:101:29 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -753,7 +753,7 @@ LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:36 + --> $DIR/bad-reg.rs:108:36 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^ @@ -761,7 +761,7 @@ LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is ava = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:139:27 + --> $DIR/bad-reg.rs:131:27 | LL | asm!("", in("cr") x); | ^ @@ -769,7 +769,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:142:28 + --> $DIR/bad-reg.rs:134:28 | LL | asm!("", out("cr") x); | ^ @@ -777,7 +777,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:145:33 + --> $DIR/bad-reg.rs:137:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -785,7 +785,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:152:28 + --> $DIR/bad-reg.rs:144:28 | LL | asm!("", in("ctr") x); | ^ @@ -793,7 +793,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:155:29 + --> $DIR/bad-reg.rs:147:29 | LL | asm!("", out("ctr") x); | ^ @@ -801,7 +801,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:158:34 + --> $DIR/bad-reg.rs:150:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -809,7 +809,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:165:27 + --> $DIR/bad-reg.rs:157:27 | LL | asm!("", in("lr") x); | ^ @@ -817,7 +817,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:168:28 + --> $DIR/bad-reg.rs:160:28 | LL | asm!("", out("lr") x); | ^ @@ -825,7 +825,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:171:33 + --> $DIR/bad-reg.rs:163:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -833,7 +833,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:178:28 + --> $DIR/bad-reg.rs:170:28 | LL | asm!("", in("xer") x); | ^ @@ -841,7 +841,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:181:29 + --> $DIR/bad-reg.rs:173:29 | LL | asm!("", out("xer") x); | ^ @@ -849,7 +849,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:184:34 + --> $DIR/bad-reg.rs:176:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -857,7 +857,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:338:18 + --> $DIR/bad-reg.rs:330:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr index 5c4cd71c2d1ad..88a8cecf40550 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -1,131 +1,131 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:139:18 + --> $DIR/bad-reg.rs:131:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:142:18 + --> $DIR/bad-reg.rs:134:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:145:26 + --> $DIR/bad-reg.rs:137:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:148:26 + --> $DIR/bad-reg.rs:140:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:152:18 + --> $DIR/bad-reg.rs:144:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:155:18 + --> $DIR/bad-reg.rs:147:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:158:26 + --> $DIR/bad-reg.rs:150:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:161:26 + --> $DIR/bad-reg.rs:153:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:165:18 + --> $DIR/bad-reg.rs:157:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:168:18 + --> $DIR/bad-reg.rs:160:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:171:26 + --> $DIR/bad-reg.rs:163:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:174:26 + --> $DIR/bad-reg.rs:166:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:178:18 + --> $DIR/bad-reg.rs:170:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:181:18 + --> $DIR/bad-reg.rs:173:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:184:26 + --> $DIR/bad-reg.rs:176:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:187:26 + --> $DIR/bad-reg.rs:179:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:183:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:185:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:187:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:189:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:199:31 + --> $DIR/bad-reg.rs:191:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:201:31 + --> $DIR/bad-reg.rs:193:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:203:31 + --> $DIR/bad-reg.rs:195:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:205:31 + --> $DIR/bad-reg.rs:197:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:200:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:202:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:204:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:206:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:208:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:210:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:220:31 + --> $DIR/bad-reg.rs:212:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:222:31 + --> $DIR/bad-reg.rs:214:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:224:31 + --> $DIR/bad-reg.rs:216:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:226:31 + --> $DIR/bad-reg.rs:218:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:220:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:222:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:224:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:226:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:228:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:230:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:232:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:234:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:236:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:238:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:240:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:242:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:264:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:266:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:268:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:270:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:264:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:266:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:268:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:270:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:272:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:274:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:276:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:278:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:280:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:282:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:284:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:286:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:328:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:330:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:332:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:334:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,145 +701,145 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:340:26 + --> $DIR/bad-reg.rs:332:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: cannot use register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:55:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", out("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:59:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", in("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:65:18 + --> $DIR/bad-reg.rs:58:18 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:68:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:71:26 + --> $DIR/bad-reg.rs:64:26 | LL | asm!("/* {} */", in(vreg) v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:73:26 + --> $DIR/bad-reg.rs:66:26 | LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:76:26 + --> $DIR/bad-reg.rs:69:26 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:79:26 + --> $DIR/bad-reg.rs:72:26 | LL | asm!("/* {} */", out(vreg) _); // requires altivec | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:90:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:92:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:102:18 + --> $DIR/bad-reg.rs:94:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:18 + --> $DIR/bad-reg.rs:98:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:109:18 + --> $DIR/bad-reg.rs:101:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:112:26 + --> $DIR/bad-reg.rs:104:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:114:26 + --> $DIR/bad-reg.rs:106:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:116:26 + --> $DIR/bad-reg.rs:108:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:111:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:139:27 + --> $DIR/bad-reg.rs:131:27 | LL | asm!("", in("cr") x); | ^ @@ -847,7 +847,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:142:28 + --> $DIR/bad-reg.rs:134:28 | LL | asm!("", out("cr") x); | ^ @@ -855,7 +855,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:145:33 + --> $DIR/bad-reg.rs:137:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -863,7 +863,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:152:28 + --> $DIR/bad-reg.rs:144:28 | LL | asm!("", in("ctr") x); | ^ @@ -871,7 +871,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:155:29 + --> $DIR/bad-reg.rs:147:29 | LL | asm!("", out("ctr") x); | ^ @@ -879,7 +879,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:158:34 + --> $DIR/bad-reg.rs:150:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -887,7 +887,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:165:27 + --> $DIR/bad-reg.rs:157:27 | LL | asm!("", in("lr") x); | ^ @@ -895,7 +895,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:168:28 + --> $DIR/bad-reg.rs:160:28 | LL | asm!("", out("lr") x); | ^ @@ -903,7 +903,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:171:33 + --> $DIR/bad-reg.rs:163:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -911,7 +911,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:178:28 + --> $DIR/bad-reg.rs:170:28 | LL | asm!("", in("xer") x); | ^ @@ -919,7 +919,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:181:29 + --> $DIR/bad-reg.rs:173:29 | LL | asm!("", out("xer") x); | ^ @@ -927,7 +927,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:184:34 + --> $DIR/bad-reg.rs:176:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -935,7 +935,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:338:18 + --> $DIR/bad-reg.rs:330:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index 151bb5682e03b..6a438798840ef 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -1,131 +1,131 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:139:18 + --> $DIR/bad-reg.rs:131:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:142:18 + --> $DIR/bad-reg.rs:134:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:145:26 + --> $DIR/bad-reg.rs:137:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:148:26 + --> $DIR/bad-reg.rs:140:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:152:18 + --> $DIR/bad-reg.rs:144:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:155:18 + --> $DIR/bad-reg.rs:147:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:158:26 + --> $DIR/bad-reg.rs:150:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:161:26 + --> $DIR/bad-reg.rs:153:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:165:18 + --> $DIR/bad-reg.rs:157:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:168:18 + --> $DIR/bad-reg.rs:160:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:171:26 + --> $DIR/bad-reg.rs:163:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:174:26 + --> $DIR/bad-reg.rs:166:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:178:18 + --> $DIR/bad-reg.rs:170:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:181:18 + --> $DIR/bad-reg.rs:173:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:184:26 + --> $DIR/bad-reg.rs:176:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:187:26 + --> $DIR/bad-reg.rs:179:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:183:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:185:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:187:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:189:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:199:31 + --> $DIR/bad-reg.rs:191:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:201:31 + --> $DIR/bad-reg.rs:193:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:203:31 + --> $DIR/bad-reg.rs:195:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:205:31 + --> $DIR/bad-reg.rs:197:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:200:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:202:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:204:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:206:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:208:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:210:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:220:31 + --> $DIR/bad-reg.rs:212:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:222:31 + --> $DIR/bad-reg.rs:214:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:224:31 + --> $DIR/bad-reg.rs:216:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:226:31 + --> $DIR/bad-reg.rs:218:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:220:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:222:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:224:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:226:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:228:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:230:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:232:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:234:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:236:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:238:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:240:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:242:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:264:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:266:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:268:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:270:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:264:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:266:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:268:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:270:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:272:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:274:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:276:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:278:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:280:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:282:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:284:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:286:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:328:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:330:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:332:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:334:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,35 +701,35 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:340:26 + --> $DIR/bad-reg.rs:332:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:59:27 + --> $DIR/bad-reg.rs:52:27 | LL | asm!("", in("v0") v64x2); // requires vsx | ^^^^^ | - = note: this is required to use type `i64x2` with register class `vreg` + = note: this is required to use type `Simd` with register class `vreg` error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:62:28 + --> $DIR/bad-reg.rs:55:28 | LL | asm!("", out("v0") v64x2); // requires vsx | ^^^^^ | - = note: this is required to use type `i64x2` with register class `vreg` + = note: this is required to use type `Simd` with register class `vreg` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:65:27 + --> $DIR/bad-reg.rs:58:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -737,7 +737,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:68:28 + --> $DIR/bad-reg.rs:61:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -745,15 +745,15 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: `vsx` target feature is not enabled - --> $DIR/bad-reg.rs:73:35 + --> $DIR/bad-reg.rs:66:35 | LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx | ^^^^^ | - = note: this is required to use type `i64x2` with register class `vreg` + = note: this is required to use type `Simd` with register class `vreg` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:76:35 + --> $DIR/bad-reg.rs:69:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -761,67 +761,67 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:90:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:92:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:102:18 + --> $DIR/bad-reg.rs:94:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:18 + --> $DIR/bad-reg.rs:98:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:109:18 + --> $DIR/bad-reg.rs:101:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:112:26 + --> $DIR/bad-reg.rs:104:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:114:26 + --> $DIR/bad-reg.rs:106:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:116:26 + --> $DIR/bad-reg.rs:108:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:111:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:139:27 + --> $DIR/bad-reg.rs:131:27 | LL | asm!("", in("cr") x); | ^ @@ -829,7 +829,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:142:28 + --> $DIR/bad-reg.rs:134:28 | LL | asm!("", out("cr") x); | ^ @@ -837,7 +837,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:145:33 + --> $DIR/bad-reg.rs:137:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -845,7 +845,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:152:28 + --> $DIR/bad-reg.rs:144:28 | LL | asm!("", in("ctr") x); | ^ @@ -853,7 +853,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:155:29 + --> $DIR/bad-reg.rs:147:29 | LL | asm!("", out("ctr") x); | ^ @@ -861,7 +861,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:158:34 + --> $DIR/bad-reg.rs:150:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -869,7 +869,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:165:27 + --> $DIR/bad-reg.rs:157:27 | LL | asm!("", in("lr") x); | ^ @@ -877,7 +877,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:168:28 + --> $DIR/bad-reg.rs:160:28 | LL | asm!("", out("lr") x); | ^ @@ -885,7 +885,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:171:33 + --> $DIR/bad-reg.rs:163:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -893,7 +893,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:178:28 + --> $DIR/bad-reg.rs:170:28 | LL | asm!("", in("xer") x); | ^ @@ -901,7 +901,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:181:29 + --> $DIR/bad-reg.rs:173:29 | LL | asm!("", out("xer") x); | ^ @@ -909,7 +909,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:184:34 + --> $DIR/bad-reg.rs:176:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -917,7 +917,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:338:18 + --> $DIR/bad-reg.rs:330:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index c7373780e382c..d6317e32bd8fb 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -1,131 +1,131 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:139:18 + --> $DIR/bad-reg.rs:131:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:142:18 + --> $DIR/bad-reg.rs:134:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:145:26 + --> $DIR/bad-reg.rs:137:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:148:26 + --> $DIR/bad-reg.rs:140:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:152:18 + --> $DIR/bad-reg.rs:144:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:155:18 + --> $DIR/bad-reg.rs:147:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:158:26 + --> $DIR/bad-reg.rs:150:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:161:26 + --> $DIR/bad-reg.rs:153:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:165:18 + --> $DIR/bad-reg.rs:157:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:168:18 + --> $DIR/bad-reg.rs:160:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:171:26 + --> $DIR/bad-reg.rs:163:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:174:26 + --> $DIR/bad-reg.rs:166:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:178:18 + --> $DIR/bad-reg.rs:170:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:181:18 + --> $DIR/bad-reg.rs:173:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:184:26 + --> $DIR/bad-reg.rs:176:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:187:26 + --> $DIR/bad-reg.rs:179:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:183:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:185:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:187:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:189:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:199:31 + --> $DIR/bad-reg.rs:191:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:201:31 + --> $DIR/bad-reg.rs:193:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:203:31 + --> $DIR/bad-reg.rs:195:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:205:31 + --> $DIR/bad-reg.rs:197:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:200:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:202:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:204:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:206:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:208:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:210:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:220:31 + --> $DIR/bad-reg.rs:212:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:222:31 + --> $DIR/bad-reg.rs:214:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:224:31 + --> $DIR/bad-reg.rs:216:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:226:31 + --> $DIR/bad-reg.rs:218:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:220:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:222:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:224:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:226:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:228:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:230:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:232:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:234:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:236:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:238:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:240:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:242:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:264:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:266:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:268:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:270:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:264:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:266:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:268:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:270:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:272:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:274:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:276:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:278:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:280:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:282:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:284:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:286:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:328:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:330:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:332:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:334:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,19 +701,19 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:340:26 + --> $DIR/bad-reg.rs:332:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:65:27 + --> $DIR/bad-reg.rs:58:27 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -721,7 +721,7 @@ LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:68:28 + --> $DIR/bad-reg.rs:61:28 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ @@ -729,7 +729,7 @@ LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:76:35 + --> $DIR/bad-reg.rs:69:35 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ @@ -737,7 +737,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:106:28 + --> $DIR/bad-reg.rs:98:28 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -745,7 +745,7 @@ LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:109:29 + --> $DIR/bad-reg.rs:101:29 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -753,7 +753,7 @@ LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:116:36 + --> $DIR/bad-reg.rs:108:36 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^ @@ -761,7 +761,7 @@ LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is ava = note: register class `vsreg` supports these types: f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:139:27 + --> $DIR/bad-reg.rs:131:27 | LL | asm!("", in("cr") x); | ^ @@ -769,7 +769,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:142:28 + --> $DIR/bad-reg.rs:134:28 | LL | asm!("", out("cr") x); | ^ @@ -777,7 +777,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:145:33 + --> $DIR/bad-reg.rs:137:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -785,7 +785,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:152:28 + --> $DIR/bad-reg.rs:144:28 | LL | asm!("", in("ctr") x); | ^ @@ -793,7 +793,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:155:29 + --> $DIR/bad-reg.rs:147:29 | LL | asm!("", out("ctr") x); | ^ @@ -801,7 +801,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:158:34 + --> $DIR/bad-reg.rs:150:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -809,7 +809,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:165:27 + --> $DIR/bad-reg.rs:157:27 | LL | asm!("", in("lr") x); | ^ @@ -817,7 +817,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:168:28 + --> $DIR/bad-reg.rs:160:28 | LL | asm!("", out("lr") x); | ^ @@ -825,7 +825,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:171:33 + --> $DIR/bad-reg.rs:163:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -833,7 +833,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:178:28 + --> $DIR/bad-reg.rs:170:28 | LL | asm!("", in("xer") x); | ^ @@ -841,7 +841,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:181:29 + --> $DIR/bad-reg.rs:173:29 | LL | asm!("", out("xer") x); | ^ @@ -849,7 +849,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:184:34 + --> $DIR/bad-reg.rs:176:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -857,7 +857,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:338:18 + --> $DIR/bad-reg.rs:330:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr b/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr index 2b4657bf358e5..86ea5eed9385d 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr @@ -1,131 +1,131 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:39:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:41:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:139:18 + --> $DIR/bad-reg.rs:131:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:142:18 + --> $DIR/bad-reg.rs:134:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:145:26 + --> $DIR/bad-reg.rs:137:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:148:26 + --> $DIR/bad-reg.rs:140:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:152:18 + --> $DIR/bad-reg.rs:144:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:155:18 + --> $DIR/bad-reg.rs:147:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:158:26 + --> $DIR/bad-reg.rs:150:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:161:26 + --> $DIR/bad-reg.rs:153:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:165:18 + --> $DIR/bad-reg.rs:157:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:168:18 + --> $DIR/bad-reg.rs:160:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:171:26 + --> $DIR/bad-reg.rs:163:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:174:26 + --> $DIR/bad-reg.rs:166:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:178:18 + --> $DIR/bad-reg.rs:170:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:181:18 + --> $DIR/bad-reg.rs:173:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:184:26 + --> $DIR/bad-reg.rs:176:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:187:26 + --> $DIR/bad-reg.rs:179:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:183:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:185:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:187:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:189:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:199:31 + --> $DIR/bad-reg.rs:191:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:201:31 + --> $DIR/bad-reg.rs:193:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:203:31 + --> $DIR/bad-reg.rs:195:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:205:31 + --> $DIR/bad-reg.rs:197:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:200:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:202:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:204:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:206:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:208:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:210:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:220:31 + --> $DIR/bad-reg.rs:212:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:222:31 + --> $DIR/bad-reg.rs:214:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:224:31 + --> $DIR/bad-reg.rs:216:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:226:31 + --> $DIR/bad-reg.rs:218:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:220:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:222:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:224:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:226:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:228:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:230:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:232:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:234:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:236:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:238:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:240:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:242:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:264:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:266:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:268:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:270:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:264:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:266:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:268:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:270:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:272:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:274:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:276:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:278:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:280:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:282:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:284:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:286:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:328:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:330:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:332:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:334:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,145 +701,145 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:340:26 + --> $DIR/bad-reg.rs:332:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: cannot use register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:55:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", out("v0") v32x4); // requires altivec | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:59:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", in("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("v0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:65:18 + --> $DIR/bad-reg.rs:58:18 | LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:68:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:71:26 + --> $DIR/bad-reg.rs:64:26 | LL | asm!("/* {} */", in(vreg) v32x4); // requires altivec | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:73:26 + --> $DIR/bad-reg.rs:66:26 | LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:76:26 + --> $DIR/bad-reg.rs:69:26 | LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^ error: register class `vreg` requires at least one of the following target features: altivec, vsx - --> $DIR/bad-reg.rs:79:26 + --> $DIR/bad-reg.rs:72:26 | LL | asm!("/* {} */", out(vreg) _); // requires altivec | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:90:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:100:18 + --> $DIR/bad-reg.rs:92:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:102:18 + --> $DIR/bad-reg.rs:94:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:18 + --> $DIR/bad-reg.rs:96:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:18 + --> $DIR/bad-reg.rs:98:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:109:18 + --> $DIR/bad-reg.rs:101:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:112:26 + --> $DIR/bad-reg.rs:104:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:114:26 + --> $DIR/bad-reg.rs:106:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:116:26 + --> $DIR/bad-reg.rs:108:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:119:26 + --> $DIR/bad-reg.rs:111:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:139:27 + --> $DIR/bad-reg.rs:131:27 | LL | asm!("", in("cr") x); | ^ @@ -847,7 +847,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:142:28 + --> $DIR/bad-reg.rs:134:28 | LL | asm!("", out("cr") x); | ^ @@ -855,7 +855,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:145:33 + --> $DIR/bad-reg.rs:137:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -863,7 +863,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:152:28 + --> $DIR/bad-reg.rs:144:28 | LL | asm!("", in("ctr") x); | ^ @@ -871,7 +871,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:155:29 + --> $DIR/bad-reg.rs:147:29 | LL | asm!("", out("ctr") x); | ^ @@ -879,7 +879,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:158:34 + --> $DIR/bad-reg.rs:150:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -887,7 +887,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:165:27 + --> $DIR/bad-reg.rs:157:27 | LL | asm!("", in("lr") x); | ^ @@ -895,7 +895,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:168:28 + --> $DIR/bad-reg.rs:160:28 | LL | asm!("", out("lr") x); | ^ @@ -903,7 +903,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:171:33 + --> $DIR/bad-reg.rs:163:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -911,7 +911,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:178:28 + --> $DIR/bad-reg.rs:170:28 | LL | asm!("", in("xer") x); | ^ @@ -919,7 +919,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:181:29 + --> $DIR/bad-reg.rs:173:29 | LL | asm!("", out("xer") x); | ^ @@ -927,7 +927,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:184:34 + --> $DIR/bad-reg.rs:176:34 | LL | asm!("/* {} */", in(xer) x); | ^ diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs index 20a2b65e2f50d..88c78859e8326 100644 --- a/tests/ui/asm/powerpc/bad-reg.rs +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -14,25 +14,18 @@ // ignore-tidy-file-linelength #![crate_type = "rlib"] -#![feature(no_core, repr_simd, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch)] #![no_core] #![allow(non_camel_case_types)] extern crate minicore; +use minicore::simd::{i32x4, i64x2}; use minicore::*; -#[repr(simd)] -pub struct i32x4([i32; 4]); -#[repr(simd)] -pub struct i64x2([i64; 2]); - -impl Copy for i32x4 {} -impl Copy for i64x2 {} - fn f() { let mut x = 0; - let mut v32x4 = i32x4([0; 4]); - let mut v64x2 = i64x2([0; 2]); + let mut v32x4 = i32x4::from_array([0; 4]); + let mut v64x2 = i64x2::from_array([0; 2]); unsafe { // Unsupported registers asm!("", out("sp") _); @@ -92,7 +85,6 @@ fn f() { asm!("", out("v30") _); asm!("", out("v31") _); - // vsreg asm!("", out("vs0") _); // always ok asm!("", in("vs0") v32x4); // requires vsx diff --git a/tests/ui/asm/s390x/bad-reg.rs b/tests/ui/asm/s390x/bad-reg.rs index 05128f8defd32..a6b2b869a851e 100644 --- a/tests/ui/asm/s390x/bad-reg.rs +++ b/tests/ui/asm/s390x/bad-reg.rs @@ -7,22 +7,18 @@ //@ ignore-backends: gcc #![crate_type = "rlib"] -#![feature(no_core, repr_simd)] +#![feature(no_core)] #![no_core] #![allow(non_camel_case_types)] extern crate minicore; +use minicore::simd::i64x2; use minicore::*; -#[repr(simd)] -pub struct i64x2([i64; 2]); - -impl Copy for i64x2 {} - fn f() { let mut x = 0; let mut b = 0u8; - let mut v = i64x2([0; 2]); + let mut v = i64x2::from_array([0; 2]); unsafe { // Unsupported registers asm!("", out("r11") _); diff --git a/tests/ui/asm/s390x/bad-reg.s390x.stderr b/tests/ui/asm/s390x/bad-reg.s390x.stderr index 7a9887a4b7cf7..cccf715a860a7 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x.stderr @@ -1,149 +1,149 @@ error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", out("r11") _); | ^^^^^^^^^^^^ error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", out("r15") _); | ^^^^^^^^^^^^ error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("c0") _); | ^^^^^^^^^^^ error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("c1") _); | ^^^^^^^^^^^ error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("c2") _); | ^^^^^^^^^^^ error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("c3") _); | ^^^^^^^^^^^ error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("c4") _); | ^^^^^^^^^^^ error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("c5") _); | ^^^^^^^^^^^ error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:40:18 | LL | asm!("", out("c6") _); | ^^^^^^^^^^^ error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:42:18 | LL | asm!("", out("c7") _); | ^^^^^^^^^^^ error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:44:18 | LL | asm!("", out("c8") _); | ^^^^^^^^^^^ error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", out("c9") _); | ^^^^^^^^^^^ error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("c10") _); | ^^^^^^^^^^^^ error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", out("c11") _); | ^^^^^^^^^^^^ error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:56:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", out("c12") _); | ^^^^^^^^^^^^ error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:58:18 + --> $DIR/bad-reg.rs:54:18 | LL | asm!("", out("c13") _); | ^^^^^^^^^^^^ error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:60:18 + --> $DIR/bad-reg.rs:56:18 | LL | asm!("", out("c14") _); | ^^^^^^^^^^^^ error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:58:18 | LL | asm!("", out("c15") _); | ^^^^^^^^^^^^ error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", out("a0") _); | ^^^^^^^^^^^ error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:62:18 | LL | asm!("", out("a1") _); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:94:18 | LL | asm!("", in("a2") x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:97:18 | LL | asm!("", out("a2") x); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:100:26 | LL | asm!("/* {} */", in(areg) x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:107:26 + --> $DIR/bad-reg.rs:103:26 | LL | asm!("/* {} */", out(areg) _); | ^^^^^^^^^^^ error: register `f0` conflicts with register `v0` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:108:31 | LL | asm!("", out("v0") _, out("f0") _); | ----------- ^^^^^^^^^^^ register `f0` @@ -151,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _); | register `v0` error: register `f1` conflicts with register `v1` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:110:31 | LL | asm!("", out("v1") _, out("f1") _); | ----------- ^^^^^^^^^^^ register `f1` @@ -159,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _); | register `v1` error: register `f2` conflicts with register `v2` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:112:31 | LL | asm!("", out("v2") _, out("f2") _); | ----------- ^^^^^^^^^^^ register `f2` @@ -167,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _); | register `v2` error: register `f3` conflicts with register `v3` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:114:31 | LL | asm!("", out("v3") _, out("f3") _); | ----------- ^^^^^^^^^^^ register `f3` @@ -175,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _); | register `v3` error: register `f4` conflicts with register `v4` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:116:31 | LL | asm!("", out("v4") _, out("f4") _); | ----------- ^^^^^^^^^^^ register `f4` @@ -183,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _); | register `v4` error: register `f5` conflicts with register `v5` - --> $DIR/bad-reg.rs:122:31 + --> $DIR/bad-reg.rs:118:31 | LL | asm!("", out("v5") _, out("f5") _); | ----------- ^^^^^^^^^^^ register `f5` @@ -191,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _); | register `v5` error: register `f6` conflicts with register `v6` - --> $DIR/bad-reg.rs:124:31 + --> $DIR/bad-reg.rs:120:31 | LL | asm!("", out("v6") _, out("f6") _); | ----------- ^^^^^^^^^^^ register `f6` @@ -199,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _); | register `v6` error: register `f7` conflicts with register `v7` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:122:31 | LL | asm!("", out("v7") _, out("f7") _); | ----------- ^^^^^^^^^^^ register `f7` @@ -207,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _); | register `v7` error: register `f8` conflicts with register `v8` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:124:31 | LL | asm!("", out("v8") _, out("f8") _); | ----------- ^^^^^^^^^^^ register `f8` @@ -215,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _); | register `v8` error: register `f9` conflicts with register `v9` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:126:31 | LL | asm!("", out("v9") _, out("f9") _); | ----------- ^^^^^^^^^^^ register `f9` @@ -223,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _); | register `v9` error: register `f10` conflicts with register `v10` - --> $DIR/bad-reg.rs:132:32 + --> $DIR/bad-reg.rs:128:32 | LL | asm!("", out("v10") _, out("f10") _); | ------------ ^^^^^^^^^^^^ register `f10` @@ -231,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _); | register `v10` error: register `f11` conflicts with register `v11` - --> $DIR/bad-reg.rs:134:32 + --> $DIR/bad-reg.rs:130:32 | LL | asm!("", out("v11") _, out("f11") _); | ------------ ^^^^^^^^^^^^ register `f11` @@ -239,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _); | register `v11` error: register `f12` conflicts with register `v12` - --> $DIR/bad-reg.rs:136:32 + --> $DIR/bad-reg.rs:132:32 | LL | asm!("", out("v12") _, out("f12") _); | ------------ ^^^^^^^^^^^^ register `f12` @@ -247,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _); | register `v12` error: register `f13` conflicts with register `v13` - --> $DIR/bad-reg.rs:138:32 + --> $DIR/bad-reg.rs:134:32 | LL | asm!("", out("v13") _, out("f13") _); | ------------ ^^^^^^^^^^^^ register `f13` @@ -255,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _); | register `v13` error: register `f14` conflicts with register `v14` - --> $DIR/bad-reg.rs:140:32 + --> $DIR/bad-reg.rs:136:32 | LL | asm!("", out("v14") _, out("f14") _); | ------------ ^^^^^^^^^^^^ register `f14` @@ -263,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _); | register `v14` error: register `f15` conflicts with register `v15` - --> $DIR/bad-reg.rs:142:32 + --> $DIR/bad-reg.rs:138:32 | LL | asm!("", out("v15") _, out("f15") _); | ------------ ^^^^^^^^^^^^ register `f15` @@ -271,73 +271,73 @@ LL | asm!("", out("v15") _, out("f15") _); | register `v15` error: invalid register `f16`: unknown register - --> $DIR/bad-reg.rs:145:32 + --> $DIR/bad-reg.rs:141:32 | LL | asm!("", out("v16") _, out("f16") _); | ^^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:71:18 + --> $DIR/bad-reg.rs:67:18 | LL | asm!("", in("v0") v); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:73:18 + --> $DIR/bad-reg.rs:69:18 | LL | asm!("", out("v0") v); | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:75:18 + --> $DIR/bad-reg.rs:71:18 | LL | asm!("", in("v0") x); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:77:18 + --> $DIR/bad-reg.rs:73:18 | LL | asm!("", out("v0") x); | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:75:18 | LL | asm!("", in("v0") b); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:78:18 | LL | asm!("", out("v0") b); | ^^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:81:26 | LL | asm!("/* {} */", in(vreg) v); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:87:26 + --> $DIR/bad-reg.rs:83:26 | LL | asm!("/* {} */", in(vreg) x); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:89:26 + --> $DIR/bad-reg.rs:85:26 | LL | asm!("/* {} */", in(vreg) b); | ^^^^^^^^^^ error: register class `vreg` requires the `vector` target feature - --> $DIR/bad-reg.rs:92:26 + --> $DIR/bad-reg.rs:88:26 | LL | asm!("/* {} */", out(vreg) _); | ^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:27 + --> $DIR/bad-reg.rs:94:27 | LL | asm!("", in("a2") x); | ^ @@ -345,7 +345,7 @@ LL | asm!("", in("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:28 + --> $DIR/bad-reg.rs:97:28 | LL | asm!("", out("a2") x); | ^ @@ -353,7 +353,7 @@ LL | asm!("", out("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:104:35 + --> $DIR/bad-reg.rs:100:35 | LL | asm!("/* {} */", in(areg) x); | ^ diff --git a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr index 4b02af95768a1..f590cb0dfc4f0 100644 --- a/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr +++ b/tests/ui/asm/s390x/bad-reg.s390x_vector.stderr @@ -1,149 +1,149 @@ error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", out("r11") _); | ^^^^^^^^^^^^ error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", out("r15") _); | ^^^^^^^^^^^^ error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("c0") _); | ^^^^^^^^^^^ error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("c1") _); | ^^^^^^^^^^^ error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", out("c2") _); | ^^^^^^^^^^^ error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("c3") _); | ^^^^^^^^^^^ error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("c4") _); | ^^^^^^^^^^^ error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("c5") _); | ^^^^^^^^^^^ error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:40:18 | LL | asm!("", out("c6") _); | ^^^^^^^^^^^ error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:42:18 | LL | asm!("", out("c7") _); | ^^^^^^^^^^^ error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:44:18 | LL | asm!("", out("c8") _); | ^^^^^^^^^^^ error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", out("c9") _); | ^^^^^^^^^^^ error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:52:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", out("c10") _); | ^^^^^^^^^^^^ error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:50:18 | LL | asm!("", out("c11") _); | ^^^^^^^^^^^^ error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:56:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", out("c12") _); | ^^^^^^^^^^^^ error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:58:18 + --> $DIR/bad-reg.rs:54:18 | LL | asm!("", out("c13") _); | ^^^^^^^^^^^^ error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:60:18 + --> $DIR/bad-reg.rs:56:18 | LL | asm!("", out("c14") _); | ^^^^^^^^^^^^ error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:62:18 + --> $DIR/bad-reg.rs:58:18 | LL | asm!("", out("c15") _); | ^^^^^^^^^^^^ error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", out("a0") _); | ^^^^^^^^^^^ error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:62:18 | LL | asm!("", out("a1") _); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:94:18 | LL | asm!("", in("a2") x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:97:18 | LL | asm!("", out("a2") x); | ^^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:100:26 | LL | asm!("/* {} */", in(areg) x); | ^^^^^^^^^^ error: register class `areg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:107:26 + --> $DIR/bad-reg.rs:103:26 | LL | asm!("/* {} */", out(areg) _); | ^^^^^^^^^^^ error: register `f0` conflicts with register `v0` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:108:31 | LL | asm!("", out("v0") _, out("f0") _); | ----------- ^^^^^^^^^^^ register `f0` @@ -151,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _); | register `v0` error: register `f1` conflicts with register `v1` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:110:31 | LL | asm!("", out("v1") _, out("f1") _); | ----------- ^^^^^^^^^^^ register `f1` @@ -159,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _); | register `v1` error: register `f2` conflicts with register `v2` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:112:31 | LL | asm!("", out("v2") _, out("f2") _); | ----------- ^^^^^^^^^^^ register `f2` @@ -167,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _); | register `v2` error: register `f3` conflicts with register `v3` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:114:31 | LL | asm!("", out("v3") _, out("f3") _); | ----------- ^^^^^^^^^^^ register `f3` @@ -175,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _); | register `v3` error: register `f4` conflicts with register `v4` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:116:31 | LL | asm!("", out("v4") _, out("f4") _); | ----------- ^^^^^^^^^^^ register `f4` @@ -183,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _); | register `v4` error: register `f5` conflicts with register `v5` - --> $DIR/bad-reg.rs:122:31 + --> $DIR/bad-reg.rs:118:31 | LL | asm!("", out("v5") _, out("f5") _); | ----------- ^^^^^^^^^^^ register `f5` @@ -191,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _); | register `v5` error: register `f6` conflicts with register `v6` - --> $DIR/bad-reg.rs:124:31 + --> $DIR/bad-reg.rs:120:31 | LL | asm!("", out("v6") _, out("f6") _); | ----------- ^^^^^^^^^^^ register `f6` @@ -199,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _); | register `v6` error: register `f7` conflicts with register `v7` - --> $DIR/bad-reg.rs:126:31 + --> $DIR/bad-reg.rs:122:31 | LL | asm!("", out("v7") _, out("f7") _); | ----------- ^^^^^^^^^^^ register `f7` @@ -207,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _); | register `v7` error: register `f8` conflicts with register `v8` - --> $DIR/bad-reg.rs:128:31 + --> $DIR/bad-reg.rs:124:31 | LL | asm!("", out("v8") _, out("f8") _); | ----------- ^^^^^^^^^^^ register `f8` @@ -215,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _); | register `v8` error: register `f9` conflicts with register `v9` - --> $DIR/bad-reg.rs:130:31 + --> $DIR/bad-reg.rs:126:31 | LL | asm!("", out("v9") _, out("f9") _); | ----------- ^^^^^^^^^^^ register `f9` @@ -223,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _); | register `v9` error: register `f10` conflicts with register `v10` - --> $DIR/bad-reg.rs:132:32 + --> $DIR/bad-reg.rs:128:32 | LL | asm!("", out("v10") _, out("f10") _); | ------------ ^^^^^^^^^^^^ register `f10` @@ -231,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _); | register `v10` error: register `f11` conflicts with register `v11` - --> $DIR/bad-reg.rs:134:32 + --> $DIR/bad-reg.rs:130:32 | LL | asm!("", out("v11") _, out("f11") _); | ------------ ^^^^^^^^^^^^ register `f11` @@ -239,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _); | register `v11` error: register `f12` conflicts with register `v12` - --> $DIR/bad-reg.rs:136:32 + --> $DIR/bad-reg.rs:132:32 | LL | asm!("", out("v12") _, out("f12") _); | ------------ ^^^^^^^^^^^^ register `f12` @@ -247,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _); | register `v12` error: register `f13` conflicts with register `v13` - --> $DIR/bad-reg.rs:138:32 + --> $DIR/bad-reg.rs:134:32 | LL | asm!("", out("v13") _, out("f13") _); | ------------ ^^^^^^^^^^^^ register `f13` @@ -255,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _); | register `v13` error: register `f14` conflicts with register `v14` - --> $DIR/bad-reg.rs:140:32 + --> $DIR/bad-reg.rs:136:32 | LL | asm!("", out("v14") _, out("f14") _); | ------------ ^^^^^^^^^^^^ register `f14` @@ -263,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _); | register `v14` error: register `f15` conflicts with register `v15` - --> $DIR/bad-reg.rs:142:32 + --> $DIR/bad-reg.rs:138:32 | LL | asm!("", out("v15") _, out("f15") _); | ------------ ^^^^^^^^^^^^ register `f15` @@ -271,13 +271,13 @@ LL | asm!("", out("v15") _, out("f15") _); | register `v15` error: invalid register `f16`: unknown register - --> $DIR/bad-reg.rs:145:32 + --> $DIR/bad-reg.rs:141:32 | LL | asm!("", out("v16") _, out("f16") _); | ^^^^^^^^^^^^ error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:79:27 + --> $DIR/bad-reg.rs:75:27 | LL | asm!("", in("v0") b); | ^ @@ -285,7 +285,7 @@ LL | asm!("", in("v0") b); = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:82:28 + --> $DIR/bad-reg.rs:78:28 | LL | asm!("", out("v0") b); | ^ @@ -293,7 +293,7 @@ LL | asm!("", out("v0") b); = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `u8` cannot be used with this register class - --> $DIR/bad-reg.rs:89:35 + --> $DIR/bad-reg.rs:85:35 | LL | asm!("/* {} */", in(vreg) b); | ^ @@ -301,7 +301,7 @@ LL | asm!("/* {} */", in(vreg) b); = note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:27 + --> $DIR/bad-reg.rs:94:27 | LL | asm!("", in("a2") x); | ^ @@ -309,7 +309,7 @@ LL | asm!("", in("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:28 + --> $DIR/bad-reg.rs:97:28 | LL | asm!("", out("a2") x); | ^ @@ -317,7 +317,7 @@ LL | asm!("", out("a2") x); = note: register class `areg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:104:35 + --> $DIR/bad-reg.rs:100:35 | LL | asm!("/* {} */", in(areg) x); | ^ diff --git a/tests/ui/issues/issue-42796.rs b/tests/ui/associated-types/cache/poison-copy-via-projection.rs similarity index 67% rename from tests/ui/issues/issue-42796.rs rename to tests/ui/associated-types/cache/poison-copy-via-projection.rs index 5e83a1cd67785..6afaccf89693d 100644 --- a/tests/ui/issues/issue-42796.rs +++ b/tests/ui/associated-types/cache/poison-copy-via-projection.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Where clause implying trait assoc type is `Copy`, poisoned cache to +//! believe `String: Copy`, which exposed UB. + pub trait Mirror { type Image; } diff --git a/tests/ui/issues/issue-42796.stderr b/tests/ui/associated-types/cache/poison-copy-via-projection.stderr similarity index 92% rename from tests/ui/issues/issue-42796.stderr rename to tests/ui/associated-types/cache/poison-copy-via-projection.stderr index 0e7ce9e98c4d7..5fd2bbd1439a2 100644 --- a/tests/ui/issues/issue-42796.stderr +++ b/tests/ui/associated-types/cache/poison-copy-via-projection.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `s` - --> $DIR/issue-42796.rs:18:20 + --> $DIR/poison-copy-via-projection.rs:22:20 | LL | let s = "Hello!".to_owned(); | - move occurs because `s` has type `String`, which does not implement the `Copy` trait diff --git a/tests/ui/issues/issue-3991.rs b/tests/ui/borrowck/push-on-nested-vec.rs similarity index 58% rename from tests/ui/issues/issue-3991.rs rename to tests/ui/borrowck/push-on-nested-vec.rs index e69c693ed49ea..bbab952e85355 100644 --- a/tests/ui/issues/issue-3991.rs +++ b/tests/ui/borrowck/push-on-nested-vec.rs @@ -1,6 +1,8 @@ +//! Regression test for . +//! Test borrowck doesn't complain on nested vector mutable reference. //@ check-pass -#![allow(dead_code)] +#![allow(dead_code)] struct HasNested { nest: Vec > , diff --git a/tests/ui/codegen/deprecated-llvm-intrinsic.rs b/tests/ui/codegen/deprecated-llvm-intrinsic.rs index 33bc5f419151a..ffa1ffc541684 100644 --- a/tests/ui/codegen/deprecated-llvm-intrinsic.rs +++ b/tests/ui/codegen/deprecated-llvm-intrinsic.rs @@ -3,18 +3,16 @@ //@ compile-flags: --target aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@ ignore-backends: gcc -#![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted, repr_simd, simd_ffi)] +#![feature(no_core, lang_items, link_llvm_intrinsics, abi_unadjusted, simd_ffi)] #![no_std] #![no_core] #![allow(internal_features, non_camel_case_types, improper_ctypes)] #![crate_type = "lib"] extern crate minicore; +use minicore::simd::i8x8; use minicore::*; -#[repr(simd)] -pub struct i8x8([i8; 8]); - extern "unadjusted" { #[deny(deprecated_llvm_intrinsic)] #[link_name = "llvm.aarch64.neon.rbit.v8i8"] diff --git a/tests/ui/codegen/deprecated-llvm-intrinsic.stderr b/tests/ui/codegen/deprecated-llvm-intrinsic.stderr index 40e4684a8ea4f..dc490deab1b61 100644 --- a/tests/ui/codegen/deprecated-llvm-intrinsic.stderr +++ b/tests/ui/codegen/deprecated-llvm-intrinsic.stderr @@ -1,11 +1,11 @@ error: using deprecated intrinsic `llvm.aarch64.neon.rbit.v8i8`, `llvm.bitreverse.v8i8` can be used instead - --> $DIR/deprecated-llvm-intrinsic.rs:21:5 + --> $DIR/deprecated-llvm-intrinsic.rs:19:5 | LL | fn foo(a: i8x8) -> i8x8; | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/deprecated-llvm-intrinsic.rs:19:12 + --> $DIR/deprecated-llvm-intrinsic.rs:17:12 | LL | #[deny(deprecated_llvm_intrinsic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/coherence/clone-impl-unsized-slice.rs similarity index 60% rename from tests/ui/issues/issue-48728.rs rename to tests/ui/coherence/clone-impl-unsized-slice.rs index 8ad9289c65cf2..6a36df0166354 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/coherence/clone-impl-unsized-slice.rs @@ -1,5 +1,5 @@ -// Regression test for #48728, an ICE that occurred computing -// coherence "help" information. +//! Regression test for . +//! ICE occurred computing coherence "help" information. //@ check-pass #[derive(Clone)] diff --git a/tests/ui/coherence/coherence-overlap-downstream-fundamental.rs b/tests/ui/coherence/coherence-overlap-downstream-fundamental.rs new file mode 100644 index 0000000000000..23482621c2f15 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream-fundamental.rs @@ -0,0 +1,28 @@ +//! Regression test for . +//! Test trait relationship defined as `Trait1 for T where T: Trait2` +//! rejects implementations of `Trait1` with generics over `#[fundamental]` +//! types, as a downstream crate can implement dependent `Trait2` for the same +//! type with the same generics, causing coherence breakage. +//! +//! This used to ICE if downstream crate tried to `impl Trait2> for A`. +//@ dont-require-annotations: NOTE + +pub trait Trait1 { + type Output; +} + +pub trait Trait2 {} + +pub struct A; + +impl Trait1 for T where T: Trait2 { + type Output = (); +} + +impl Trait1> for A { +//~^ ERROR conflicting implementations of trait +//~| NOTE downstream crates may implement trait `Trait2>` for type `A` + type Output = i32; +} + +fn main() {} diff --git a/tests/ui/issues/issue-43355.stderr b/tests/ui/coherence/coherence-overlap-downstream-fundamental.stderr similarity index 89% rename from tests/ui/issues/issue-43355.stderr rename to tests/ui/coherence/coherence-overlap-downstream-fundamental.stderr index 5a089cb3d8bbb..c96148f07b8d3 100644 --- a/tests/ui/issues/issue-43355.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream-fundamental.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait1>` for type `A` - --> $DIR/issue-43355.rs:15:1 + --> $DIR/coherence-overlap-downstream-fundamental.rs:22:1 | LL | impl Trait1 for T where T: Trait2 { | --------------------------------------------- first implementation here diff --git a/tests/ui/const-generics/mgca/static-const-arg.rs b/tests/ui/const-generics/mgca/static-const-arg.rs new file mode 100644 index 0000000000000..716c8bb6dc4de --- /dev/null +++ b/tests/ui/const-generics/mgca/static-const-arg.rs @@ -0,0 +1,18 @@ +// Regression test for #132986. +// FIXME(min_generic_const_args): using statics as direct const arguments should error instead of +// ICEing until const eval can evaluate statics to valtrees for const generics. + +#![feature(min_generic_const_args, macroless_generic_const_args)] +#![allow(incomplete_features)] + +static A: u32 = 0; + +struct Foo; + +const _: Foo<{ A }> = Foo; +//~^ ERROR static items cannot be used as const arguments + +const _: Foo = Foo; +//~^ ERROR static items cannot be used as const arguments + +fn main() {} diff --git a/tests/ui/const-generics/mgca/static-const-arg.stderr b/tests/ui/const-generics/mgca/static-const-arg.stderr new file mode 100644 index 0000000000000..9c5473f94d2cc --- /dev/null +++ b/tests/ui/const-generics/mgca/static-const-arg.stderr @@ -0,0 +1,14 @@ +error: static items cannot be used as const arguments + --> $DIR/static-const-arg.rs:12:16 + | +LL | const _: Foo<{ A }> = Foo; + | ^ + +error: static items cannot be used as const arguments + --> $DIR/static-const-arg.rs:15:14 + | +LL | const _: Foo = Foo; + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-51655.rs b/tests/ui/consts/const_in_pattern/const-bytes-slice-pattern.rs similarity index 67% rename from tests/ui/issues/issue-51655.rs rename to tests/ui/consts/const_in_pattern/const-bytes-slice-pattern.rs index 05f71623d1419..028c7a74bd640 100644 --- a/tests/ui/issues/issue-51655.rs +++ b/tests/ui/consts/const_in_pattern/const-bytes-slice-pattern.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to ICE. //@ check-pass + #![allow(dead_code)] const PATH_DOT: &[u8] = &[b'.']; diff --git a/tests/ui/crate-loading/missing-target-error.rs b/tests/ui/crate-loading/missing-target-error.rs new file mode 100644 index 0000000000000..3a75d568d2c8e --- /dev/null +++ b/tests/ui/crate-loading/missing-target-error.rs @@ -0,0 +1,13 @@ +//! Regression test for . +//! Tests that compiling for a target which is not installed will result in a helpful +//! error message. +//~^^^ ERROR can't find crate for `std` +//~| NOTE target may not be installed +//~| NOTE can't find crate + +//@ compile-flags: --target=thumbv6m-none-eabi +//@ ignore-arm +//@ needs-llvm-components: arm +//@ ignore-backends: gcc + +fn main() { } diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/crate-loading/missing-target-error.stderr similarity index 100% rename from tests/ui/issues/issue-37131.stderr rename to tests/ui/crate-loading/missing-target-error.stderr diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs b/tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo-comments.rs similarity index 85% rename from tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs rename to tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo-comments.rs index 215145a64b177..eec8c8e1d0d4e 100644 --- a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs +++ b/tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo-comments.rs @@ -1,9 +1,10 @@ -use std::fmt; +//! Auxiliary file for . +//! This is a file with many multi-byte characters, to try to encourage +//! the compiler to trip on them. The Drop implementation below will +//! need to have its source location embedded into the debug info for +//! the output file. -// This ia file with many multi-byte characters, to try to encourage -// the compiler to trip on them. The Drop implementation below will -// need to have its source location embedded into the debug info for -// the output file. +use std::fmt; // αααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααα // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ diff --git a/tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo.rs b/tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo.rs new file mode 100644 index 0000000000000..695fccc4519a8 --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/cross-crate-multibyte-debuginfo.rs @@ -0,0 +1,10 @@ +//! Auxiliary file for . +//! This is a file that pulls in a separate file as a submodule, where +//! that separate file has many multi-byte characters, to try to +//! encourage the compiler to trip on them. +#![crate_type="lib"] + +#[path = "cross-crate-multibyte-debuginfo-comments.rs"] +mod issue_24687_mbcs_in_comments; + +pub use issue_24687_mbcs_in_comments::D; diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/main.rs b/tests/ui/debuginfo/cross-crate-multibyte-debuginfo.rs similarity index 63% rename from tests/ui/issues/issue-24687-embed-debuginfo/main.rs rename to tests/ui/debuginfo/cross-crate-multibyte-debuginfo.rs index d1ab717264b4c..026aecaa5f277 100644 --- a/tests/ui/issues/issue-24687-embed-debuginfo/main.rs +++ b/tests/ui/debuginfo/cross-crate-multibyte-debuginfo.rs @@ -1,8 +1,9 @@ +//! Regression test for . //@ run-pass -//@ aux-build:issue-24687-lib.rs +//@ aux-build:cross-crate-multibyte-debuginfo.rs //@ compile-flags:-g -extern crate issue_24687_lib as d; +extern crate cross_crate_multibyte_debuginfo as d; fn main() { // Create a `D`, which has a destructor whose body will be codegen'ed diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs index aaf84514eb784..3dda014001421 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -1,5 +1,5 @@ //@ revisions: ice_155125 ice_155127 ice_155128 ice_155164 ice_155202 -//@[ice_155202] edition: 2024 +//@[ice_155202] edition: 2018.. #![feature(min_generic_const_args, fn_delegation)] diff --git a/tests/ui/issues/issue-38942.rs b/tests/ui/enum-discriminant/repr-u64-enum-discriminant-cast.rs similarity index 62% rename from tests/ui/issues/issue-38942.rs rename to tests/ui/enum-discriminant/repr-u64-enum-discriminant-cast.rs index 3f80beb53f357..c9f6d6a65ea35 100644 --- a/tests/ui/issues/issue-38942.rs +++ b/tests/ui/enum-discriminant/repr-u64-enum-discriminant-cast.rs @@ -1,5 +1,6 @@ +//! Regression test for . +//! This used to ICE when compiling for `i686-apple-darwin`. //@ run-pass -// See https://github.com/rust-lang/rust/issues/38942 #[repr(u64)] pub enum NSEventType { diff --git a/tests/ui/issues/issue-37510.rs b/tests/ui/expr/if/mut-borrow-in-else-if-after-if-let.rs similarity index 55% rename from tests/ui/issues/issue-37510.rs rename to tests/ui/expr/if/mut-borrow-in-else-if-after-if-let.rs index 62a90c5604bd9..7c95752f760c1 100644 --- a/tests/ui/issues/issue-37510.rs +++ b/tests/ui/expr/if/mut-borrow-in-else-if-after-if-let.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test that else-if after if-let is not considered a pattern guard. //@ check-pass fn foo(_: &mut i32) -> bool { true } diff --git a/tests/ui/issues/issue-50618.rs b/tests/ui/functional-struct-update/fru-unknown-field-in-closure.rs similarity index 75% rename from tests/ui/issues/issue-50618.rs rename to tests/ui/functional-struct-update/fru-unknown-field-in-closure.rs index 5f762bc431e12..c9fb4e2774938 100644 --- a/tests/ui/issues/issue-50618.rs +++ b/tests/ui/functional-struct-update/fru-unknown-field-in-closure.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ICE. + struct Point { pub x: u64, pub y: u64, diff --git a/tests/ui/issues/issue-50618.stderr b/tests/ui/functional-struct-update/fru-unknown-field-in-closure.stderr similarity index 86% rename from tests/ui/issues/issue-50618.stderr rename to tests/ui/functional-struct-update/fru-unknown-field-in-closure.stderr index 1a3514fb715d1..990e65c87aaae 100644 --- a/tests/ui/issues/issue-50618.stderr +++ b/tests/ui/functional-struct-update/fru-unknown-field-in-closure.stderr @@ -1,5 +1,5 @@ error[E0560]: struct `Point` has no field named `nonexistent` - --> $DIR/issue-50618.rs:14:13 + --> $DIR/fru-unknown-field-in-closure.rs:17:13 | LL | nonexistent: 0, | ^^^^^^^^^^^ `Point` does not have this field diff --git a/tests/ui/issues/issue-38556.rs b/tests/ui/imports/macro-use-as.rs similarity index 58% rename from tests/ui/issues/issue-38556.rs rename to tests/ui/imports/macro-use-as.rs index b04558707e148..e26a831e74b57 100644 --- a/tests/ui/issues/issue-38556.rs +++ b/tests/ui/imports/macro-use-as.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Reexport in macro caused ICE. //@ run-pass + #![allow(dead_code)] pub struct Foo; diff --git a/tests/ui/issues/issue-51116.rs b/tests/ui/inference/need_type_info/for-loop-nested-array-inference.rs similarity index 66% rename from tests/ui/issues/issue-51116.rs rename to tests/ui/inference/need_type_info/for-loop-nested-array-inference.rs index 4c21cbfc61d43..a6f35620fcc9b 100644 --- a/tests/ui/issues/issue-51116.rs +++ b/tests/ui/inference/need_type_info/for-loop-nested-array-inference.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to leak internal `__next` ident into suggestion. + fn main() { let tiles = Default::default(); for row in &mut tiles { diff --git a/tests/ui/issues/issue-51116.stderr b/tests/ui/inference/need_type_info/for-loop-nested-array-inference.stderr similarity index 81% rename from tests/ui/issues/issue-51116.stderr rename to tests/ui/inference/need_type_info/for-loop-nested-array-inference.stderr index 4839a0d46095f..75f84797cecd9 100644 --- a/tests/ui/issues/issue-51116.stderr +++ b/tests/ui/inference/need_type_info/for-loop-nested-array-inference.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/issue-51116.rs:5:13 + --> $DIR/for-loop-nested-array-inference.rs:8:13 | LL | *tile = 0; | ^^^^^ cannot infer type diff --git a/tests/ui/issues/issue-39827.rs b/tests/ui/intrinsics/volatile-zst-intrinsics.rs similarity index 80% rename from tests/ui/issues/issue-39827.rs rename to tests/ui/intrinsics/volatile-zst-intrinsics.rs index e3248c9e9ac72..0927442268d1f 100644 --- a/tests/ui/issues/issue-39827.rs +++ b/tests/ui/intrinsics/volatile-zst-intrinsics.rs @@ -1,3 +1,8 @@ +//! Regression test for . +//! This test ensures that volatile intrinsics can be specialised with +//! zero-sized types and, in case of copy/set functions, can accept +//! number of elements equal to zero. + //@ run-pass #![feature(core_intrinsics)] @@ -5,11 +10,6 @@ use std::intrinsics::{ volatile_copy_memory, volatile_store, volatile_load, volatile_copy_nonoverlapping_memory, volatile_set_memory }; -// -// This test ensures that volatile intrinsics can be specialised with -// zero-sized types and, in case of copy/set functions, can accept -// number of elements equal to zero. -// fn main () { let mut dst_pair = (1, 2); let src_pair = (3, 4); diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs b/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs deleted file mode 100644 index 5b1b1389cebb3..0000000000000 --- a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![crate_type="lib"] - -// This is a file that pulls in a separate file as a submodule, where -// that separate file has many multi-byte characters, to try to -// encourage the compiler to trip on them. - -#[path = "issue-24687-mbcs-in-comments.rs"] -mod issue_24687_mbcs_in_comments; - -pub use issue_24687_mbcs_in_comments::D; diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs deleted file mode 100644 index 875495d08ed77..0000000000000 --- a/tests/ui/issues/issue-37131.rs +++ /dev/null @@ -1,12 +0,0 @@ -//~ ERROR can't find crate for `std` -//~| NOTE target may not be installed -//~| NOTE can't find crate -// Tests that compiling for a target which is not installed will result in a helpful -// error message. - -//@ compile-flags: --target=thumbv6m-none-eabi -//@ ignore-arm -//@ needs-llvm-components: arm -//@ ignore-backends: gcc - -fn main() { } diff --git a/tests/ui/issues/issue-3779.rs b/tests/ui/issues/issue-3779.rs deleted file mode 100644 index 901c1be80ca06..0000000000000 --- a/tests/ui/issues/issue-3779.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct S { - //~^ ERROR E0072 - element: Option -} - -fn main() { - let x = S { element: None }; -} diff --git a/tests/ui/issues/issue-3779.stderr b/tests/ui/issues/issue-3779.stderr deleted file mode 100644 index d4f4b79102d5e..0000000000000 --- a/tests/ui/issues/issue-3779.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0072]: recursive type `S` has infinite size - --> $DIR/issue-3779.rs:1:1 - | -LL | struct S { - | ^^^^^^^^ -LL | -LL | element: Option - | - recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | element: Option> - | ++++ + - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-38954.rs b/tests/ui/issues/issue-38954.rs deleted file mode 100644 index 61df411b1f92b..0000000000000 --- a/tests/ui/issues/issue-38954.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn _test(ref _p: str) {} -//~^ ERROR the size for values of type - -fn main() { } diff --git a/tests/ui/issues/issue-39709.rs b/tests/ui/issues/issue-39709.rs deleted file mode 100644 index df3286721f51f..0000000000000 --- a/tests/ui/issues/issue-39709.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass -#![allow(unused_macros)] -fn main() { - println!("{}", { macro_rules! x { ($(t:tt)*) => {} } 33 }); -} diff --git a/tests/ui/issues/issue-39808.rs b/tests/ui/issues/issue-39808.rs deleted file mode 100644 index 99e3d9b4bcdfd..0000000000000 --- a/tests/ui/issues/issue-39808.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-pass -#![allow(unreachable_code)] - -// Regression test for #39808. The type parameter of `Owned` was -// considered to be "unconstrained" because the type resulting from -// `format!` (`String`) was not being propagated upward, owing to the -// fact that the expression diverges. - -use std::borrow::Cow; - -fn main() { - let _ = if false { - Cow::Owned(format!("{:?}", panic!())) - } else { - Cow::Borrowed("") - }; -} diff --git a/tests/ui/issues/issue-43355.rs b/tests/ui/issues/issue-43355.rs deleted file mode 100644 index 597472b4f48f0..0000000000000 --- a/tests/ui/issues/issue-43355.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ dont-require-annotations: NOTE - -pub trait Trait1 { - type Output; -} - -pub trait Trait2 {} - -pub struct A; - -impl Trait1 for T where T: Trait2 { - type Output = (); -} - -impl Trait1> for A { -//~^ ERROR conflicting implementations of trait -//~| NOTE downstream crates may implement trait `Trait2>` for type `A` - type Output = i32; -} - -fn main() {} diff --git a/tests/ui/issues/issue-46771.rs b/tests/ui/issues/issue-46771.rs deleted file mode 100644 index 22be8d6af8a7f..0000000000000 --- a/tests/ui/issues/issue-46771.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - struct Foo; - (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `Foo` -} diff --git a/tests/ui/issues/issue-4759-1.rs b/tests/ui/issues/issue-4759-1.rs deleted file mode 100644 index 7368a7b2f845b..0000000000000 --- a/tests/ui/issues/issue-4759-1.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ run-pass -trait U { fn f(self); } -impl U for isize { fn f(self) {} } -pub fn main() { 4.f(); } diff --git a/tests/ui/issues/issue-5315.rs b/tests/ui/issues/issue-5315.rs deleted file mode 100644 index 29a6f8f2934a1..0000000000000 --- a/tests/ui/issues/issue-5315.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass - -struct A(#[allow(dead_code)] bool); - -pub fn main() { - let f = A; - f(true); -} diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs b/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs deleted file mode 100644 index a496e58a79bdd..0000000000000 --- a/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Pin's PartialEq implementation allowed to access the pointer allowing for -// unsoundness by using Rc::get_mut to move value within Rc. -// See https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73 for more details. - -use std::ops::Deref; -use std::pin::Pin; -use std::rc::Rc; - -struct Apple; - -impl Deref for Apple { - type Target = Apple; - fn deref(&self) -> &Apple { - &Apple - } -} - -impl PartialEq> for Apple { - fn eq(&self, _rc: &Rc) -> bool { - unreachable!() - } -} - -fn main() { - let _ = Pin::new(Apple) == Rc::pin(Apple); - //~^ ERROR type mismatch resolving -} diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr deleted file mode 100644 index 9164e4696eb34..0000000000000 --- a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0271]: type mismatch resolving ` as Deref>::Target == Rc` - --> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29 - | -LL | let _ = Pin::new(Apple) == Rc::pin(Apple); - | ^^ expected `Rc`, found `Apple` - | - = note: expected struct `Rc` - found struct `Apple` - = note: required for `Pin` to implement `PartialEq>>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/iterators/rpit-method-chain-no-ice.rs b/tests/ui/iterators/rpit-method-chain-no-ice.rs new file mode 100644 index 0000000000000..170653f0eeaf3 --- /dev/null +++ b/tests/ui/iterators/rpit-method-chain-no-ice.rs @@ -0,0 +1,14 @@ +//! Regression test for #159685 + +struct EntriesBuffer(Box<[u8]>); + +impl EntriesBuffer { + fn has_lifetime(&self) -> impl Iterator { + //~^ ERROR expected `IterMut<'_, u8>` to be an iterator that yields `&mut str`, but it yields `&mut u8` + self.0.iter_mut() + } +} + +fn main() { + EntriesBuffer(vec![0u8].into_boxed_slice()).has_lifetime(); +} diff --git a/tests/ui/iterators/rpit-method-chain-no-ice.stderr b/tests/ui/iterators/rpit-method-chain-no-ice.stderr new file mode 100644 index 0000000000000..74e33cecf3523 --- /dev/null +++ b/tests/ui/iterators/rpit-method-chain-no-ice.stderr @@ -0,0 +1,22 @@ +error[E0271]: expected `IterMut<'_, u8>` to be an iterator that yields `&mut str`, but it yields `&mut u8` + --> $DIR/rpit-method-chain-no-ice.rs:6:31 + | +LL | fn has_lifetime(&self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&mut str`, found `&mut u8` +LL | +LL | self.0.iter_mut() + | ----------------- return type was inferred to be `std::slice::IterMut<'_, u8>` here + | + = note: expected mutable reference `&mut str` + found mutable reference `&mut u8` +note: the method call chain might not have had the expected associated types + --> $DIR/rpit-method-chain-no-ice.rs:8:16 + | +LL | self.0.iter_mut() + | ------ ^^^^^^^^^^ `Iterator::Item` is `&mut u8` here + | | + | this expression has type `Box<[u8]>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/layout/randomize.rs b/tests/ui/layout/randomize.rs index 27e99327a3196..eaeb527f191cb 100644 --- a/tests/ui/layout/randomize.rs +++ b/tests/ui/layout/randomize.rs @@ -49,6 +49,52 @@ const _: () = { assert!(std::mem::offset_of!(Result::<&usize, ()>, Ok.0) == 0); }; +// these types only have their size checked, they're never constructed. +// these repr(Rust) types must remain zero-sized. +#[allow(dead_code)] +pub struct UnitStruct; +#[allow(dead_code)] +pub struct EmptyTupleStruct(); +#[allow(dead_code)] +pub struct EmptyStruct {} +#[allow(dead_code)] +pub struct ZstFieldsTupleStruct((), [u64; 0], [u8; 0], [(); 42]); +#[allow(dead_code)] +pub struct ZstFieldsStruct { + a: (), + b: [u64; 0], + c: [u8; 0], + d: [(); 42], +} +#[allow(dead_code)] +pub enum EmptyEnum {} +#[allow(dead_code)] +pub enum SingleUnitVariantEnum { A } +#[allow(dead_code)] +pub enum SingleZstFieldTupleVariantEnum { A((), [u64; 0], [u8; 0], [(); 42]) } +#[allow(dead_code)] +pub enum SingleZstFieldVariantEnum { + A { + a: (), + b: [u64; 0], + c: [u8; 0], + d: [(); 42], + } +} + +// all these types must remain zero-sized. +const _: () = { + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); + assert!(size_of::() == 0); +}; + #[allow(dead_code)] struct Unsizable(usize, T); diff --git a/tests/ui/issues/issue-37884.rs b/tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.rs similarity index 70% rename from tests/ui/issues/issue-37884.rs rename to tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.rs index 3480942d9d282..11a1397c8ef09 100644 --- a/tests/ui/issues/issue-37884.rs +++ b/tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! This used to leak compiler data structures in error message. //@ dont-require-annotations: NOTE struct RepeatMut<'a, T>(T, &'a ()); diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.stderr similarity index 86% rename from tests/ui/issues/issue-37884.stderr rename to tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.stderr index a7a19e3c6dfdc..c3e1ed6e2641e 100644 --- a/tests/ui/issues/issue-37884.stderr +++ b/tests/ui/lifetimes/lifetime-errors/iterator-next-extra-named-lifetime.stderr @@ -1,5 +1,5 @@ error[E0308]: method not compatible with trait - --> $DIR/issue-37884.rs:8:5 + --> $DIR/iterator-next-extra-named-lifetime.rs:10:5 | LL | fn next(&'a mut self) -> Option | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -9,7 +9,7 @@ LL | fn next(&'a mut self) -> Option note: the anonymous lifetime as defined here... --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL note: ...does not necessarily outlive the lifetime `'a` as defined here - --> $DIR/issue-37884.rs:5:6 + --> $DIR/iterator-next-extra-named-lifetime.rs:7:6 | LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { | ^^ diff --git a/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr b/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr index c9c15e2d62c9f..c6a53d4face4f 100644 --- a/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr +++ b/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr @@ -1,15 +1,15 @@ error[E0080]: values of the type `[u8; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/any.rs:LL:COL | - = note: evaluation of `std::any::try_as_dyn::<[u8; usize::MAX], dyn Trait>::{constant#0}` failed inside this call -note: inside `TypeId::trait_info_of::` + = note: evaluation of `std::any::try_as_dyn::<'_, [u8; usize::MAX], dyn Trait>::{constant#0}` failed inside this call +note: inside `TypeId::trait_info_of::<'_, dyn Trait>` --> $SRC_DIR/core/src/any.rs:LL:COL note: inside `TypeId::trait_info_of_trait_type_id` --> $SRC_DIR/core/src/any.rs:LL:COL note: inside `type_info::::size` --> $SRC_DIR/core/src/mem/type_info.rs:LL:COL -note: the above error was encountered while instantiating `fn try_as_dyn::<[u8; usize::MAX], dyn Trait>` +note: the above error was encountered while instantiating `fn try_as_dyn::<'_, [u8; usize::MAX], dyn Trait>` --> $DIR/vtable-try-as-dyn.rs:14:13 | LL | let _ = std::any::try_as_dyn::<[u8; usize::MAX], dyn Trait>(x); diff --git a/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr b/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr index c9c15e2d62c9f..c6a53d4face4f 100644 --- a/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr +++ b/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr @@ -1,15 +1,15 @@ error[E0080]: values of the type `[u8; usize::MAX]` are too big for the target architecture --> $SRC_DIR/core/src/any.rs:LL:COL | - = note: evaluation of `std::any::try_as_dyn::<[u8; usize::MAX], dyn Trait>::{constant#0}` failed inside this call -note: inside `TypeId::trait_info_of::` + = note: evaluation of `std::any::try_as_dyn::<'_, [u8; usize::MAX], dyn Trait>::{constant#0}` failed inside this call +note: inside `TypeId::trait_info_of::<'_, dyn Trait>` --> $SRC_DIR/core/src/any.rs:LL:COL note: inside `TypeId::trait_info_of_trait_type_id` --> $SRC_DIR/core/src/any.rs:LL:COL note: inside `type_info::::size` --> $SRC_DIR/core/src/mem/type_info.rs:LL:COL -note: the above error was encountered while instantiating `fn try_as_dyn::<[u8; usize::MAX], dyn Trait>` +note: the above error was encountered while instantiating `fn try_as_dyn::<'_, [u8; usize::MAX], dyn Trait>` --> $DIR/vtable-try-as-dyn.rs:14:13 | LL | let _ = std::any::try_as_dyn::<[u8; usize::MAX], dyn Trait>(x); diff --git a/tests/ui/issues/issue-43250.rs b/tests/ui/lowering/expr-metavar-in-let-pattern.rs similarity index 60% rename from tests/ui/issues/issue-43250.rs rename to tests/ui/lowering/expr-metavar-in-let-pattern.rs index 24d70d2964bb2..3f10576e31010 100644 --- a/tests/ui/issues/issue-43250.rs +++ b/tests/ui/lowering/expr-metavar-in-let-pattern.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test expr metavars aren't allowed in places where pattern is expected, +//! and their use doesn't cause ICE. + fn main() { let mut y; const C: u32 = 0; diff --git a/tests/ui/issues/issue-43250.stderr b/tests/ui/lowering/expr-metavar-in-let-pattern.stderr similarity index 81% rename from tests/ui/issues/issue-43250.stderr rename to tests/ui/lowering/expr-metavar-in-let-pattern.stderr index e74342b85adb3..6161a7ed50e05 100644 --- a/tests/ui/issues/issue-43250.stderr +++ b/tests/ui/lowering/expr-metavar-in-let-pattern.stderr @@ -1,5 +1,5 @@ error: arbitrary expressions aren't allowed in patterns - --> $DIR/issue-43250.rs:9:8 + --> $DIR/expr-metavar-in-let-pattern.rs:13:8 | LL | m!(y); | ^ @@ -7,7 +7,7 @@ LL | m!(y); = note: the `expr` fragment specifier forces the metavariable's content to be an expression error: arbitrary expressions aren't allowed in patterns - --> $DIR/issue-43250.rs:11:8 + --> $DIR/expr-metavar-in-let-pattern.rs:15:8 | LL | m!(C); | ^ diff --git a/tests/ui/issues/issue-43424.rs b/tests/ui/macros/attr-path-metavar-generic-args.rs similarity index 60% rename from tests/ui/issues/issue-43424.rs rename to tests/ui/macros/attr-path-metavar-generic-args.rs index b3f76d8b04992..389d37f07c437 100644 --- a/tests/ui/issues/issue-43424.rs +++ b/tests/ui/macros/attr-path-metavar-generic-args.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test generics in attribute paths are rejected. + #![allow(unused)] macro_rules! m { diff --git a/tests/ui/issues/issue-43424.stderr b/tests/ui/macros/attr-path-metavar-generic-args.stderr similarity index 71% rename from tests/ui/issues/issue-43424.stderr rename to tests/ui/macros/attr-path-metavar-generic-args.stderr index 64a3c2a3d8d06..ac60ec0cafa5b 100644 --- a/tests/ui/issues/issue-43424.stderr +++ b/tests/ui/macros/attr-path-metavar-generic-args.stderr @@ -1,5 +1,5 @@ error: unexpected generic arguments in path - --> $DIR/issue-43424.rs:10:10 + --> $DIR/attr-path-metavar-generic-args.rs:13:10 | LL | m!(inline); | ^^^^ diff --git a/tests/ui/issues/issue-39848.rs b/tests/ui/macros/macro-adjacent-ident-on-token.rs similarity index 61% rename from tests/ui/issues/issue-39848.rs rename to tests/ui/macros/macro-adjacent-ident-on-token.rs index 2a059120e8175..5e57f427724aa 100644 --- a/tests/ui/issues/issue-39848.rs +++ b/tests/ui/macros/macro-adjacent-ident-on-token.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ice on `IllFormedSpan`. + macro_rules! get_opt { ($tgt:expr, $field:ident) => { if $tgt.has_$field() {} //~ ERROR expected `{`, found identifier `foo` diff --git a/tests/ui/issues/issue-39848.stderr b/tests/ui/macros/macro-adjacent-ident-on-token.stderr similarity index 88% rename from tests/ui/issues/issue-39848.stderr rename to tests/ui/macros/macro-adjacent-ident-on-token.stderr index 1ffed2d4a1da1..b13a3d45828d3 100644 --- a/tests/ui/issues/issue-39848.stderr +++ b/tests/ui/macros/macro-adjacent-ident-on-token.stderr @@ -1,5 +1,5 @@ error: expected `{`, found identifier `foo` - --> $DIR/issue-39848.rs:3:21 + --> $DIR/macro-adjacent-ident-on-token.rs:6:21 | LL | if $tgt.has_$field() {} | ^^^^^^ expected `{` @@ -8,7 +8,7 @@ LL | get_opt!(bar, foo); | ------------------ in this macro invocation | note: the `if` expression is missing a block after this condition - --> $DIR/issue-39848.rs:3:12 + --> $DIR/macro-adjacent-ident-on-token.rs:6:12 | LL | if $tgt.has_$field() {} | ^^^^^^^^^ diff --git a/tests/ui/macros/macro-rules-def-in-block-expr.rs b/tests/ui/macros/macro-rules-def-in-block-expr.rs new file mode 100644 index 0000000000000..4074c6c9cac1e --- /dev/null +++ b/tests/ui/macros/macro-rules-def-in-block-expr.rs @@ -0,0 +1,8 @@ +//! Regression test for . +//! Macro definition inside block expression caused ICE. +//@ run-pass + +#![allow(unused_macros)] +fn main() { + println!("{}", { macro_rules! x { ($(t:tt)*) => {} } 33 }); +} diff --git a/tests/ui/issues/issue-5067.rs b/tests/ui/macros/repetition-matches-empty-token-tree.rs similarity index 92% rename from tests/ui/issues/issue-5067.rs rename to tests/ui/macros/repetition-matches-empty-token-tree.rs index 47d07f0df014c..eb722764fc63a 100644 --- a/tests/ui/issues/issue-5067.rs +++ b/tests/ui/macros/repetition-matches-empty-token-tree.rs @@ -1,10 +1,11 @@ -#![allow(unused_macros)] - -// Tests that repetition matchers cannot match the empty token tree (since that would be -// ambiguous). +//! Regression test for . +//! Tests that repetition matchers cannot match the empty token tree (since that would be +//! ambiguous). //@ edition:2018 +#![allow(unused_macros)] + macro_rules! foo { ( $()* ) => {}; //~^ ERROR repetition matches empty token tree diff --git a/tests/ui/issues/issue-5067.stderr b/tests/ui/macros/repetition-matches-empty-token-tree.stderr similarity index 67% rename from tests/ui/issues/issue-5067.stderr rename to tests/ui/macros/repetition-matches-empty-token-tree.stderr index 7ffc6071407c5..eba436c233ca7 100644 --- a/tests/ui/issues/issue-5067.stderr +++ b/tests/ui/macros/repetition-matches-empty-token-tree.stderr @@ -1,107 +1,107 @@ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:9:8 + --> $DIR/repetition-matches-empty-token-tree.rs:10:8 | LL | ( $()* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:11:8 + --> $DIR/repetition-matches-empty-token-tree.rs:12:8 | LL | ( $()+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:13:8 + --> $DIR/repetition-matches-empty-token-tree.rs:14:8 | LL | ( $()? ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:18:9 + --> $DIR/repetition-matches-empty-token-tree.rs:19:9 | LL | ( [$()*] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:20:9 + --> $DIR/repetition-matches-empty-token-tree.rs:21:9 | LL | ( [$()+] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:22:9 + --> $DIR/repetition-matches-empty-token-tree.rs:23:9 | LL | ( [$()?] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:27:8 + --> $DIR/repetition-matches-empty-token-tree.rs:28:8 | LL | ( $($()* $(),* $(a)* $(a),* )* ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:29:8 + --> $DIR/repetition-matches-empty-token-tree.rs:30:8 | LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:31:8 + --> $DIR/repetition-matches-empty-token-tree.rs:32:8 | LL | ( $($()* $(),* $(a)* $(a),* )? ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:33:8 + --> $DIR/repetition-matches-empty-token-tree.rs:34:8 | LL | ( $($()? $(),* $(a)? $(a),* )* ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:35:8 + --> $DIR/repetition-matches-empty-token-tree.rs:36:8 | LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:37:8 + --> $DIR/repetition-matches-empty-token-tree.rs:38:8 | LL | ( $($()? $(),* $(a)? $(a),* )? ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:47:12 + --> $DIR/repetition-matches-empty-token-tree.rs:48:12 | LL | ( $(a $()+)* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:49:12 + --> $DIR/repetition-matches-empty-token-tree.rs:50:12 | LL | ( $(a $()*)+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:51:12 + --> $DIR/repetition-matches-empty-token-tree.rs:52:12 | LL | ( $(a $()+)? ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:53:12 + --> $DIR/repetition-matches-empty-token-tree.rs:54:12 | LL | ( $(a $()?)+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:60:18 + --> $DIR/repetition-matches-empty-token-tree.rs:61:18 | LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); | ^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:71:8 + --> $DIR/repetition-matches-empty-token-tree.rs:72:8 | LL | ( $()* ) => {}; | ^^ diff --git a/tests/ui/issues/issue-3895.rs b/tests/ui/match/guard-arm-and-or-arm.rs similarity index 63% rename from tests/ui/issues/issue-3895.rs rename to tests/ui/match/guard-arm-and-or-arm.rs index 6bd173d48785b..0296ee0d3cc3c 100644 --- a/tests/ui/issues/issue-3895.rs +++ b/tests/ui/match/guard-arm-and-or-arm.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Match with guard arm and or pattern used to ICE. //@ run-pass + #![allow(dead_code)] pub fn main() { diff --git a/tests/ui/issues/issue-3702-2.rs b/tests/ui/methods/ambig-method-call-in-trait-impl.rs similarity index 79% rename from tests/ui/issues/issue-3702-2.rs rename to tests/ui/methods/ambig-method-call-in-trait-impl.rs index d47f6d248f708..260ca0b546a3f 100644 --- a/tests/ui/issues/issue-3702-2.rs +++ b/tests/ui/methods/ambig-method-call-in-trait-impl.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to trigger LLVM assertion. + pub trait ToPrimitive { fn to_int(&self) -> isize { 0 } } diff --git a/tests/ui/issues/issue-3702-2.stderr b/tests/ui/methods/ambig-method-call-in-trait-impl.stderr similarity index 85% rename from tests/ui/issues/issue-3702-2.stderr rename to tests/ui/methods/ambig-method-call-in-trait-impl.stderr index 448263aafd44e..0482346d9a482 100644 --- a/tests/ui/issues/issue-3702-2.stderr +++ b/tests/ui/methods/ambig-method-call-in-trait-impl.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/issue-3702-2.rs:16:14 + --> $DIR/ambig-method-call-in-trait-impl.rs:19:14 | LL | self.to_int() + other.to_int() | ^^^^^^ multiple `to_int` found | note: candidate #1 is defined in an impl of the trait `Add` for the type `isize` - --> $DIR/issue-3702-2.rs:14:5 + --> $DIR/ambig-method-call-in-trait-impl.rs:17:5 | LL | fn to_int(&self) -> isize { *self } | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `ToPrimitive` for the type `isize` - --> $DIR/issue-3702-2.rs:2:5 + --> $DIR/ambig-method-call-in-trait-impl.rs:5:5 | LL | fn to_int(&self) -> isize { 0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/methods/by-value-self-method-on-int.rs b/tests/ui/methods/by-value-self-method-on-int.rs new file mode 100644 index 0000000000000..c27898b156d86 --- /dev/null +++ b/tests/ui/methods/by-value-self-method-on-int.rs @@ -0,0 +1,7 @@ +//! Regression test for . +//! This used to trigger LLVM assertion. +//@ run-pass + +trait U { fn f(self); } +impl U for isize { fn f(self) {} } +pub fn main() { 4.f(); } diff --git a/tests/ui/issues/issue-4759.rs b/tests/ui/methods/destructure-and-call-self-method.rs similarity index 60% rename from tests/ui/issues/issue-4759.rs rename to tests/ui/methods/destructure-and-call-self-method.rs index 4b49442b4010f..a88276ec774f1 100644 --- a/tests/ui/issues/issue-4759.rs +++ b/tests/ui/methods/destructure-and-call-self-method.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Destructuring a struct and calling consuming method used to segfault. //@ run-pass + #![allow(non_shorthand_field_patterns)] struct T { a: Box } diff --git a/tests/ui/mir/hoist_deref_early_else.rs b/tests/ui/mir/hoist_deref_early_else.rs new file mode 100644 index 0000000000000..fb749e96d7c08 --- /dev/null +++ b/tests/ui/mir/hoist_deref_early_else.rs @@ -0,0 +1,36 @@ +//! Regression test for issue . +//! The null pointer `p` should never be dereferenced. +//@ run-pass +//@ revisions: noopt opt +//@ check-run-results +//@[noopt] compile-flags: -C opt-level=0 +//@[opt] compile-flags: -C opt-level=3 + +use std::hint::black_box; + +#[inline(never)] +fn foo(q: u64, p: *const u64) -> u64 { + unsafe { + 'a: { + match q { + 1 => match *p { + 1 => break 'a 100, + _ => {} + }, + 2 => match *p { + 2 => break 'a 200, + _ => {} + }, + _ => {} + } + 999 + } + } +} + +fn main() { + let q: u64 = black_box(3); + let p: *const u64 = black_box(std::ptr::null()); + let r = foo(q, p); + assert_eq!(999, black_box(r)); +} diff --git a/tests/ui/issues/issue-52262.rs b/tests/ui/moves/move-out-of-shared-ref-deref.rs similarity index 89% rename from tests/ui/issues/issue-52262.rs rename to tests/ui/moves/move-out-of-shared-ref-deref.rs index 547643f0d6e20..6adb7811c5d4d 100644 --- a/tests/ui/issues/issue-52262.rs +++ b/tests/ui/moves/move-out-of-shared-ref-deref.rs @@ -1,3 +1,5 @@ +//! Regression test for . + #[derive(Debug)] enum MyError { NotFound { key: Vec }, diff --git a/tests/ui/issues/issue-52262.stderr b/tests/ui/moves/move-out-of-shared-ref-deref.stderr similarity index 92% rename from tests/ui/issues/issue-52262.stderr rename to tests/ui/moves/move-out-of-shared-ref-deref.stderr index 51959f22b97a4..7a7158dfbdbef 100644 --- a/tests/ui/issues/issue-52262.stderr +++ b/tests/ui/moves/move-out-of-shared-ref-deref.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `*key` which is behind a shared reference - --> $DIR/issue-52262.rs:15:35 + --> $DIR/move-out-of-shared-ref-deref.rs:17:35 | LL | String::from_utf8(*key).unwrap() | ^^^^ move occurs because `*key` has type `Vec`, which does not implement the `Copy` trait diff --git a/tests/ui/issues/issue-3847.rs b/tests/ui/parser/other-module-struct-match.rs similarity index 63% rename from tests/ui/issues/issue-3847.rs rename to tests/ui/parser/other-module-struct-match.rs index 73aaab4183694..c9c7a9d52dbc1 100644 --- a/tests/ui/issues/issue-3847.rs +++ b/tests/ui/parser/other-module-struct-match.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Pattern matching struct from different module caused parser to fail. //@ run-pass + mod buildings { pub struct Tower { pub height: usize } } diff --git a/tests/ui/issues/issue-3753.rs b/tests/ui/parser/pub-method-after-attribute.rs similarity index 79% rename from tests/ui/issues/issue-3753.rs rename to tests/ui/parser/pub-method-after-attribute.rs index a243ceab83ebe..828fc52189b32 100644 --- a/tests/ui/issues/issue-3753.rs +++ b/tests/ui/parser/pub-method-after-attribute.rs @@ -1,7 +1,6 @@ +//! Regression test for . +//! Pub keyword after attribute caused parser to fail. //@ run-pass -// Issue #3656 -// Issue Name: pub method preceded by attribute can't be parsed -// Abstract: Visibility parsing failed when compiler parsing use std::f64; diff --git a/tests/ui/issues/issue-51102.rs b/tests/ui/pattern/struct-pattern-nonexistent-field.rs similarity index 84% rename from tests/ui/issues/issue-51102.rs rename to tests/ui/pattern/struct-pattern-nonexistent-field.rs index b5ddc7221d06a..ed74bdf937145 100644 --- a/tests/ui/issues/issue-51102.rs +++ b/tests/ui/pattern/struct-pattern-nonexistent-field.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test matching non-existing fields via struct pattern syntax in closures doesn't ICE. + enum SimpleEnum { NoState, } diff --git a/tests/ui/issues/issue-51102.stderr b/tests/ui/pattern/struct-pattern-nonexistent-field.stderr similarity index 85% rename from tests/ui/issues/issue-51102.stderr rename to tests/ui/pattern/struct-pattern-nonexistent-field.stderr index 09c52292dccaf..4eddc55bb5490 100644 --- a/tests/ui/issues/issue-51102.stderr +++ b/tests/ui/pattern/struct-pattern-nonexistent-field.stderr @@ -1,5 +1,5 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state` - --> $DIR/issue-51102.rs:13:17 + --> $DIR/struct-pattern-nonexistent-field.rs:16:17 | LL | state: 0, | ^^^^^ @@ -8,7 +8,7 @@ LL | state: 0, | help: `SimpleStruct` has a field named `no_state_here` error[E0025]: field `no_state_here` bound multiple times in the pattern - --> $DIR/issue-51102.rs:24:17 + --> $DIR/struct-pattern-nonexistent-field.rs:27:17 | LL | no_state_here: 0, | ---------------- first use of `no_state_here` @@ -16,7 +16,7 @@ LL | no_state_here: 1 | ^^^^^^^^^^^^^^^^ multiple uses of `no_state_here` in pattern error[E0026]: variant `SimpleEnum::NoState` does not have a field named `state` - --> $DIR/issue-51102.rs:33:17 + --> $DIR/struct-pattern-nonexistent-field.rs:36:17 | LL | state: 0 | ^^^^^ variant `SimpleEnum::NoState` does not have this field diff --git a/tests/ui/issues/issue-42880.rs b/tests/ui/pattern/type-alias-as-variant-pattern.rs similarity index 57% rename from tests/ui/issues/issue-42880.rs rename to tests/ui/pattern/type-alias-as-variant-pattern.rs index 36d15fc35b48a..092357d0ceb96 100644 --- a/tests/ui/issues/issue-42880.rs +++ b/tests/ui/pattern/type-alias-as-variant-pattern.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test type-based paths in variant patterns don't cause ICE. + type Value = String; fn main() { diff --git a/tests/ui/issues/issue-42880.stderr b/tests/ui/pattern/type-alias-as-variant-pattern.stderr similarity index 87% rename from tests/ui/issues/issue-42880.stderr rename to tests/ui/pattern/type-alias-as-variant-pattern.stderr index 8743b1cfdef77..9ecff58c41c0d 100644 --- a/tests/ui/issues/issue-42880.stderr +++ b/tests/ui/pattern/type-alias-as-variant-pattern.stderr @@ -1,5 +1,5 @@ error[E0599]: no associated function or constant named `String` found for struct `String` in the current scope - --> $DIR/issue-42880.rs:4:22 + --> $DIR/type-alias-as-variant-pattern.rs:7:22 | LL | let f = |&Value::String(_)| (); | ^^^^^^ associated function or constant not found in `String` diff --git a/tests/ui/issues/issue-38857.rs b/tests/ui/privacy/locally-pub-private-module-access.rs similarity index 57% rename from tests/ui/issues/issue-38857.rs rename to tests/ui/privacy/locally-pub-private-module-access.rs index 63a0af759a3de..7939219b6a999 100644 --- a/tests/ui/issues/issue-38857.rs +++ b/tests/ui/privacy/locally-pub-private-module-access.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Trying to access locally pub but inaccessible items caused ICE. + fn main() { let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; //~^ ERROR: cannot find `imp` in `sys` [E0433] diff --git a/tests/ui/issues/issue-38857.stderr b/tests/ui/privacy/locally-pub-private-module-access.stderr similarity index 85% rename from tests/ui/issues/issue-38857.stderr rename to tests/ui/privacy/locally-pub-private-module-access.stderr index 85a0c266ac657..5f69f1a660923 100644 --- a/tests/ui/issues/issue-38857.stderr +++ b/tests/ui/privacy/locally-pub-private-module-access.stderr @@ -1,11 +1,11 @@ error[E0433]: cannot find `imp` in `sys` - --> $DIR/issue-38857.rs:2:23 + --> $DIR/locally-pub-private-module-access.rs:5:23 | LL | let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; | ^^^ could not find `imp` in `sys` error[E0603]: module `sys` is private - --> $DIR/issue-38857.rs:2:18 + --> $DIR/locally-pub-private-module-access.rs:5:18 | LL | let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; | ^^^ private module diff --git a/tests/ui/issues/issue-50415.rs b/tests/ui/range/inclusive-range-in-closure.rs similarity index 71% rename from tests/ui/issues/issue-50415.rs rename to tests/ui/range/inclusive-range-in-closure.rs index 5f6211eb149dd..b842fed586608 100644 --- a/tests/ui/issues/issue-50415.rs +++ b/tests/ui/range/inclusive-range-in-closure.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Test inclusive ranges in closures don't ICE. //@ run-pass + fn main() { // Simplified test case let _ = || 0..=1; diff --git a/tests/ui/reflection/trait_info_of_too_big.stderr b/tests/ui/reflection/trait_info_of_too_big.stderr index b5dc1d3cdb44a..8d8557670e816 100644 --- a/tests/ui/reflection/trait_info_of_too_big.stderr +++ b/tests/ui/reflection/trait_info_of_too_big.stderr @@ -15,7 +15,7 @@ error[E0080]: values of the type `[u8; usize::MAX]` are too big for the target a LL | TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_::{constant#0}` failed inside this call | -note: inside `TypeId::trait_info_of::` +note: inside `TypeId::trait_info_of::<'_, dyn Trait>` --> $SRC_DIR/core/src/any.rs:LL:COL note: inside `TypeId::trait_info_of_trait_type_id` --> $SRC_DIR/core/src/any.rs:LL:COL diff --git a/tests/ui/issues/issue-47094.rs b/tests/ui/repr/conflicting-repr-enum-attrs.rs similarity index 58% rename from tests/ui/issues/issue-47094.rs rename to tests/ui/repr/conflicting-repr-enum-attrs.rs index c5d37feb1447f..d7e629d230c02 100644 --- a/tests/ui/issues/issue-47094.rs +++ b/tests/ui/repr/conflicting-repr-enum-attrs.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test `conflicting representation hints` warning is being triggered +//! when there are multiple repr attributes. + #[repr(C, u8)] //~ ERROR conflicting representation hints //~^ WARN this was previously accepted enum Foo { diff --git a/tests/ui/issues/issue-47094.stderr b/tests/ui/repr/conflicting-repr-enum-attrs.stderr similarity index 90% rename from tests/ui/issues/issue-47094.stderr rename to tests/ui/repr/conflicting-repr-enum-attrs.stderr index da414d68214a8..6810a2a2a1171 100644 --- a/tests/ui/issues/issue-47094.stderr +++ b/tests/ui/repr/conflicting-repr-enum-attrs.stderr @@ -1,5 +1,5 @@ error[E0566]: conflicting representation hints - --> $DIR/issue-47094.rs:1:8 + --> $DIR/conflicting-repr-enum-attrs.rs:5:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -9,7 +9,7 @@ LL | #[repr(C, u8)] = note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default error[E0566]: conflicting representation hints - --> $DIR/issue-47094.rs:8:8 + --> $DIR/conflicting-repr-enum-attrs.rs:12:8 | LL | #[repr(C)] | ^ @@ -25,7 +25,7 @@ error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0566`. Future incompatibility report: Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/issue-47094.rs:1:8 + --> $DIR/conflicting-repr-enum-attrs.rs:5:8 | LL | #[repr(C, u8)] | ^ ^^ @@ -36,7 +36,7 @@ LL | #[repr(C, u8)] Future breakage diagnostic: error[E0566]: conflicting representation hints - --> $DIR/issue-47094.rs:8:8 + --> $DIR/conflicting-repr-enum-attrs.rs:12:8 | LL | #[repr(C)] | ^ diff --git a/tests/ui/issues/issue-44216-add-instant.rs b/tests/ui/std/instant-add-duration-overflow.rs similarity index 53% rename from tests/ui/issues/issue-44216-add-instant.rs rename to tests/ui/std/instant-add-duration-overflow.rs index ca2c52b99a82a..519dbcac69c0f 100644 --- a/tests/ui/issues/issue-44216-add-instant.rs +++ b/tests/ui/std/instant-add-duration-overflow.rs @@ -1,5 +1,8 @@ +//! Regression test for . +//! Test overflowing `Instant` panics. //@ run-fail //@ error-pattern:overflow +//@ needs-subprocess use std::time::{Duration, Instant}; diff --git a/tests/ui/issues/issue-44216-sub-instant.rs b/tests/ui/std/instant-sub-duration-overflow.rs similarity index 62% rename from tests/ui/issues/issue-44216-sub-instant.rs rename to tests/ui/std/instant-sub-duration-overflow.rs index 19cd12e685fd1..0009b2800040b 100644 --- a/tests/ui/issues/issue-44216-sub-instant.rs +++ b/tests/ui/std/instant-sub-duration-overflow.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test overflowing `Instant` panics. //@ run-fail //@ error-pattern:overflow //@ needs-subprocess diff --git a/tests/ui/issues/issue-44216-add-system-time.rs b/tests/ui/std/system-time-add-duration-overflow.rs similarity index 63% rename from tests/ui/issues/issue-44216-add-system-time.rs rename to tests/ui/std/system-time-add-duration-overflow.rs index 3838d28e33d1b..a920afa5ed799 100644 --- a/tests/ui/issues/issue-44216-add-system-time.rs +++ b/tests/ui/std/system-time-add-duration-overflow.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test overflowing `SystemTime` panics. //@ run-fail //@ error-pattern:overflow //@ needs-subprocess diff --git a/tests/ui/issues/issue-44216-sub-system-time.rs b/tests/ui/std/system-time-sub-duration-overflow.rs similarity index 63% rename from tests/ui/issues/issue-44216-sub-system-time.rs rename to tests/ui/std/system-time-sub-duration-overflow.rs index bd4f66f3e161b..64d88b527028f 100644 --- a/tests/ui/issues/issue-44216-sub-system-time.rs +++ b/tests/ui/std/system-time-sub-duration-overflow.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test overflowing `SystemTime` panics. //@ run-fail //@ error-pattern:overflow //@ needs-subprocess diff --git a/tests/ui/structs-enums/call-tuple-struct-ctor-as-fn.rs b/tests/ui/structs-enums/call-tuple-struct-ctor-as-fn.rs new file mode 100644 index 0000000000000..b715c9d3eaab2 --- /dev/null +++ b/tests/ui/structs-enums/call-tuple-struct-ctor-as-fn.rs @@ -0,0 +1,10 @@ +//! Regression test for . +//! Test calling tuple struct constructor doesn't cause segfault. +//@ run-pass + +struct A(#[allow(dead_code)] bool); + +pub fn main() { + let f = A; + f(true); +} diff --git a/tests/ui/issues/issue-4736.rs b/tests/ui/structs/tuple-struct-init-with-named-field.rs similarity index 56% rename from tests/ui/issues/issue-4736.rs rename to tests/ui/structs/tuple-struct-init-with-named-field.rs index 799d2d4809860..586d96284e170 100644 --- a/tests/ui/issues/issue-4736.rs +++ b/tests/ui/structs/tuple-struct-init-with-named-field.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ICE. + struct NonCopyable(()); fn main() { diff --git a/tests/ui/issues/issue-4736.stderr b/tests/ui/structs/tuple-struct-init-with-named-field.stderr similarity index 90% rename from tests/ui/issues/issue-4736.stderr rename to tests/ui/structs/tuple-struct-init-with-named-field.stderr index b099e528ca8a8..1fb3b0be0b02e 100644 --- a/tests/ui/issues/issue-4736.stderr +++ b/tests/ui/structs/tuple-struct-init-with-named-field.stderr @@ -1,5 +1,5 @@ error[E0560]: struct `NonCopyable` has no field named `p` - --> $DIR/issue-4736.rs:4:26 + --> $DIR/tuple-struct-init-with-named-field.rs:7:26 | LL | struct NonCopyable(()); | ----------- `NonCopyable` defined here diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.fixed similarity index 73% rename from tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed rename to tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.fixed index d8402cdf07e38..157ed7e609d07 100644 --- a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed +++ b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.fixed @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test reference suggestion correctly puts cast in parentheses. //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.rs similarity index 73% rename from tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs rename to tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.rs index 0e04680911c80..3657cc67f7588 100644 --- a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs +++ b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test reference suggestion correctly puts cast in parentheses. //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.stderr similarity index 83% rename from tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr rename to tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.stderr index 211dd51289595..61b309291438c 100644 --- a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr +++ b/tests/ui/suggestions/borrow-cast-or-binexpr-with-parens.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:12:42 + --> $DIR/borrow-cast-or-binexpr-with-parens.rs:14:42 | LL | light_flows_our_war_of_mocking_words(behold as usize); | ------------------------------------ ^^^^^^^^^^^^^^^ expected `&usize`, found `usize` @@ -7,7 +7,7 @@ LL | light_flows_our_war_of_mocking_words(behold as usize); | arguments to this function are incorrect | note: function defined here - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4 + --> $DIR/borrow-cast-or-binexpr-with-parens.rs:7:4 | LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- @@ -17,7 +17,7 @@ LL | light_flows_our_war_of_mocking_words(&(behold as usize)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:14:42 + --> $DIR/borrow-cast-or-binexpr-with-parens.rs:16:42 | LL | light_flows_our_war_of_mocking_words(with_tears + 4); | ------------------------------------ ^^^^^^^^^^^^^^ expected `&usize`, found `usize` @@ -25,7 +25,7 @@ LL | light_flows_our_war_of_mocking_words(with_tears + 4); | arguments to this function are incorrect | note: function defined here - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4 + --> $DIR/borrow-cast-or-binexpr-with-parens.rs:7:4 | LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- diff --git a/tests/ui/suggestions/suggest-swap.rs b/tests/ui/suggestions/suggest-swap.rs new file mode 100644 index 0000000000000..ef6604a42b2c0 --- /dev/null +++ b/tests/ui/suggestions/suggest-swap.rs @@ -0,0 +1,14 @@ +//! Regression test for +use std::mem; + +fn main() { + let mut arr = [1, 2, 3]; + + let i = 0usize; + let j = 1usize; + + mem::swap( + &mut arr[i], + &mut arr[j], //~ ERROR cannot borrow `arr[_]` as mutable more than once at a time + ); +} diff --git a/tests/ui/suggestions/suggest-swap.stderr b/tests/ui/suggestions/suggest-swap.stderr new file mode 100644 index 0000000000000..85fbbfb7e743c --- /dev/null +++ b/tests/ui/suggestions/suggest-swap.stderr @@ -0,0 +1,22 @@ +error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time + --> $DIR/suggest-swap.rs:12:9 + | +LL | mem::swap( + | --------- first borrow later used by call +LL | &mut arr[i], + | ----------- first mutable borrow occurs here +LL | &mut arr[j], + | ^^^^^^^^^^^ second mutable borrow occurs here + | +help: use `.swap()` to swap elements at the specified indices instead + | +LL - mem::swap( +LL - &mut arr[i], +LL - &mut arr[j], +LL - ); +LL + arr.swap(j, i); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-43853.rs b/tests/ui/traits/coerce-diverging-through-from.rs similarity index 64% rename from tests/ui/issues/issue-43853.rs rename to tests/ui/traits/coerce-diverging-through-from.rs index ed07314531c3d..024d21daec264 100644 --- a/tests/ui/issues/issue-43853.rs +++ b/tests/ui/traits/coerce-diverging-through-from.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test using `From::from(f())` on a diverging `f()` doesn't ICE. //@ run-pass //@ needs-unwind diff --git a/tests/ui/issues/issue-47309.rs b/tests/ui/traits/default-method/mono-item-collector-on-impl-with-lifetimes.rs similarity index 54% rename from tests/ui/issues/issue-47309.rs rename to tests/ui/traits/default-method/mono-item-collector-on-impl-with-lifetimes.rs index 99f1ccbc5758c..44c1e171835c8 100644 --- a/tests/ui/issues/issue-47309.rs +++ b/tests/ui/traits/default-method/mono-item-collector-on-impl-with-lifetimes.rs @@ -1,6 +1,6 @@ -// Make sure that the mono-item collector does not crash when trying to -// instantiate a default impl of a method with lifetime parameters. -// See https://github.com/rust-lang/rust/issues/47309 +//! Regression test for . +//! Make sure that the mono-item collector does not crash when trying to +//! instantiate a default impl of a method with lifetime parameters. //@ compile-flags:-Clink-dead-code //@ build-pass diff --git a/tests/ui/issues/issue-3979-2.rs b/tests/ui/traits/default-method/nested-supertrait-method-in-default-body.rs similarity index 55% rename from tests/ui/issues/issue-3979-2.rs rename to tests/ui/traits/default-method/nested-supertrait-method-in-default-body.rs index 98b6e85225db5..5516b58e57624 100644 --- a/tests/ui/issues/issue-3979-2.rs +++ b/tests/ui/traits/default-method/nested-supertrait-method-in-default-body.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test calling nested supertrait's method in default method body works. //@ check-pass trait A { diff --git a/tests/ui/issues/issue-3979.rs b/tests/ui/traits/default-method/supertrait-method-in-default-body.rs similarity index 79% rename from tests/ui/issues/issue-3979.rs rename to tests/ui/traits/default-method/supertrait-method-in-default-body.rs index 238df225f0f34..597ff6375c7a2 100644 --- a/tests/ui/issues/issue-3979.rs +++ b/tests/ui/traits/default-method/supertrait-method-in-default-body.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Test calling supertrait's method in default method body works. //@ run-pass + #![allow(dead_code)] #![allow(non_snake_case)] diff --git a/tests/ui/issues/issue-51907.rs b/tests/ui/traits/object/extern-c-trait-object-methods.rs similarity index 75% rename from tests/ui/issues/issue-51907.rs rename to tests/ui/traits/object/extern-c-trait-object-methods.rs index bf3f629df4970..f1ee19fc67cf2 100644 --- a/tests/ui/issues/issue-51907.rs +++ b/tests/ui/traits/object/extern-c-trait-object-methods.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Test extern `C` trait object methods don't ICE. //@ run-pass + trait Foo { extern "C" fn borrow(&self); extern "C" fn take(self: Box); diff --git a/tests/ui/issues/issue-3702.rs b/tests/ui/traits/object/nested-trait-method-call.rs similarity index 54% rename from tests/ui/issues/issue-3702.rs rename to tests/ui/traits/object/nested-trait-method-call.rs index bb79e3a7f9384..c63671ba48a43 100644 --- a/tests/ui/issues/issue-3702.rs +++ b/tests/ui/traits/object/nested-trait-method-call.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Calling method of trait defined in function used to trigger LLVM assertion. //@ run-pass + #![allow(dead_code)] pub fn main() { diff --git a/tests/ui/type-inference/diverging-expr-unconstrained-type-param.rs b/tests/ui/type-inference/diverging-expr-unconstrained-type-param.rs new file mode 100644 index 0000000000000..1e523dcc66ea0 --- /dev/null +++ b/tests/ui/type-inference/diverging-expr-unconstrained-type-param.rs @@ -0,0 +1,17 @@ +//! Regression test for . +//! The type parameter of `Owned` was considered to be "unconstrained" +//! because the type resulting from `format!` (`String`) was not being +//! propagated upward, owing to the fact that the expression diverges. +//@ run-pass + +#![allow(unreachable_code)] + +use std::borrow::Cow; + +fn main() { + let _ = if false { + Cow::Owned(format!("{:?}", panic!())) + } else { + Cow::Borrowed("") + }; +} diff --git a/tests/ui/typeck/call-unit-struct-as-fn.rs b/tests/ui/typeck/call-unit-struct-as-fn.rs new file mode 100644 index 0000000000000..2fe2085dd72a9 --- /dev/null +++ b/tests/ui/typeck/call-unit-struct-as-fn.rs @@ -0,0 +1,7 @@ +//! Regression test for . +//! Test calling unit struct as fn doesn't ICE. + +fn main() { + struct Foo; + (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `Foo` +} diff --git a/tests/ui/issues/issue-46771.stderr b/tests/ui/typeck/call-unit-struct-as-fn.stderr similarity index 90% rename from tests/ui/issues/issue-46771.stderr rename to tests/ui/typeck/call-unit-struct-as-fn.stderr index fab55fbfd704a..8056d0df57f99 100644 --- a/tests/ui/issues/issue-46771.stderr +++ b/tests/ui/typeck/call-unit-struct-as-fn.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `Foo` - --> $DIR/issue-46771.rs:3:23 + --> $DIR/call-unit-struct-as-fn.rs:6:23 | LL | struct Foo; | ---------- `Foo` defined here diff --git a/tests/ui/issues/issue-37665.rs b/tests/ui/unpretty/mir-unpretty-type-error.rs similarity index 62% rename from tests/ui/issues/issue-37665.rs rename to tests/ui/unpretty/mir-unpretty-type-error.rs index db74b1f025987..4b48a0126ac51 100644 --- a/tests/ui/issues/issue-37665.rs +++ b/tests/ui/unpretty/mir-unpretty-type-error.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! Test type error when compiling with `unpretty=mir` doesn't ICE. //@ compile-flags: -Z unpretty=mir use std::path::MAIN_SEPARATOR; diff --git a/tests/ui/issues/issue-37665.stderr b/tests/ui/unpretty/mir-unpretty-type-error.stderr similarity index 86% rename from tests/ui/issues/issue-37665.stderr rename to tests/ui/unpretty/mir-unpretty-type-error.stderr index 2c404b4e74473..f0c19a23ed0e4 100644 --- a/tests/ui/issues/issue-37665.stderr +++ b/tests/ui/unpretty/mir-unpretty-type-error.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-37665.rs:9:17 + --> $DIR/mir-unpretty-type-error.rs:11:17 | LL | let x: () = 0; | -- ^ expected `()`, found integer diff --git a/tests/ui/issues/issue-48131.rs b/tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.rs similarity index 89% rename from tests/ui/issues/issue-48131.rs rename to tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.rs index a1084ea243b26..92b9bbfefc88e 100644 --- a/tests/ui/issues/issue-48131.rs +++ b/tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.rs @@ -1,3 +1,5 @@ +//! Regression test for . + // This note is annotated because the purpose of the test // is to ensure that certain other notes are not generated. #![deny(unused_unsafe)] diff --git a/tests/ui/issues/issue-48131.stderr b/tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.stderr similarity index 72% rename from tests/ui/issues/issue-48131.stderr rename to tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.stderr index fe0cd4efae891..cc5fab4fcdf94 100644 --- a/tests/ui/issues/issue-48131.stderr +++ b/tests/ui/unsafe/unused-unsafe-in-nested-fn-lint.stderr @@ -1,17 +1,17 @@ error: unnecessary `unsafe` block - --> $DIR/issue-48131.rs:9:9 + --> $DIR/unused-unsafe-in-nested-fn-lint.rs:11:9 | LL | unsafe { /* unnecessary */ } | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/issue-48131.rs:3:9 + --> $DIR/unused-unsafe-in-nested-fn-lint.rs:5:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ error: unnecessary `unsafe` block - --> $DIR/issue-48131.rs:19:13 + --> $DIR/unused-unsafe-in-nested-fn-lint.rs:21:13 | LL | unsafe { /* unnecessary */ } | ^^^^^^ unnecessary `unsafe` block diff --git a/tests/ui/unsized/unsized-ref-fn-param.rs b/tests/ui/unsized/unsized-ref-fn-param.rs new file mode 100644 index 0000000000000..9a36e82b049fe --- /dev/null +++ b/tests/ui/unsized/unsized-ref-fn-param.rs @@ -0,0 +1,7 @@ +//! Regression test for . +//! Test we emit helpful error message instead of silently failing. + +fn _test(ref _p: str) {} +//~^ ERROR the size for values of type + +fn main() { } diff --git a/tests/ui/issues/issue-38954.stderr b/tests/ui/unsized/unsized-ref-fn-param.stderr similarity index 93% rename from tests/ui/issues/issue-38954.stderr rename to tests/ui/unsized/unsized-ref-fn-param.stderr index bd9c5e4197bc7..3fa5758d2083a 100644 --- a/tests/ui/issues/issue-38954.stderr +++ b/tests/ui/unsized/unsized-ref-fn-param.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-38954.rs:1:18 + --> $DIR/unsized-ref-fn-param.rs:4:18 | LL | fn _test(ref _p: str) {} | ^^^ doesn't have a size known at compile-time