diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index b852d71b8008..4f1594d02a82 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -714,7 +714,7 @@ impl LayoutCalculator { }, fields: FieldsShape::Arbitrary { offsets: [niche_offset].into(), - memory_index: [0].into(), + in_memory_order: [FieldIdx::new(0)].into(), }, backend_repr: abi, largest_niche, @@ -1008,8 +1008,8 @@ impl LayoutCalculator { let pair = LayoutData::::scalar_pair(&self.cx, tag, prim_scalar); let pair_offsets = match pair.fields { - FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index.raw, [0, 1]); + FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => { + assert_eq!(in_memory_order.raw, [FieldIdx::new(0), FieldIdx::new(1)]); offsets } _ => panic!("encountered a non-arbitrary layout during enum layout"), @@ -1061,7 +1061,7 @@ impl LayoutCalculator { }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), - memory_index: [0].into(), + in_memory_order: [FieldIdx::new(0)].into(), }, largest_niche, uninhabited, @@ -1110,10 +1110,10 @@ impl LayoutCalculator { let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; - let mut inverse_memory_index: IndexVec = fields.indices().collect(); + let mut in_memory_order: IndexVec = fields.indices().collect(); let optimize_field_order = !repr.inhibit_struct_field_reordering(); let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; - let optimizing = &mut inverse_memory_index.raw[..end]; + let optimizing = &mut in_memory_order.raw[..end]; let fields_excluding_tail = &fields.raw[..end]; // unsizable tail fields are excluded so that we use the same seed for the sized and unsized layouts. let field_seed = fields_excluding_tail @@ -1248,12 +1248,10 @@ impl LayoutCalculator { // regardless of the status of `-Z randomize-layout` } } - // inverse_memory_index holds field indices by increasing memory offset. - // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5. + // in_memory_order holds field indices by increasing memory offset. + // That is, if field 5 has offset 0, the first element of in_memory_order is 5. // We now write field offsets to the corresponding offset slot; // field 5 with offset 0 puts 0 in offsets[5]. - // At the bottom of this function, we invert `inverse_memory_index` to - // produce `memory_index` (see `invert_mapping`). let mut unsized_field = None::<&F>; let mut offsets = IndexVec::from_elem(Size::ZERO, fields); let mut offset = Size::ZERO; @@ -1265,7 +1263,7 @@ impl LayoutCalculator { align = align.max(prefix_align); offset = prefix_size.align_to(prefix_align); } - for &i in &inverse_memory_index { + for &i in &in_memory_order { let field = &fields[i]; if let Some(unsized_field) = unsized_field { return Err(LayoutCalculatorError::UnexpectedUnsized(*unsized_field)); @@ -1322,18 +1320,6 @@ impl LayoutCalculator { debug!("univariant min_size: {:?}", offset); let min_size = offset; - // As stated above, inverse_memory_index holds field indices by increasing offset. - // This makes it an already-sorted view of the offsets vec. - // To invert it, consider: - // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. - // Field 5 would be the first element, so memory_index is i: - // Note: if we didn't optimize, it's already right. - let memory_index = if optimize_field_order { - inverse_memory_index.invert_bijective_mapping() - } else { - debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); - inverse_memory_index.into_iter().map(|it| it.index() as u32).collect() - }; let size = min_size.align_to(align); // FIXME(oli-obk): deduplicate and harden these checks if size.bytes() >= dl.obj_size_bound() { @@ -1389,8 +1375,11 @@ impl LayoutCalculator { let pair = LayoutData::::scalar_pair(&self.cx, a, b); let pair_offsets = match pair.fields { - FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index.raw, [0, 1]); + FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => { + assert_eq!( + in_memory_order.raw, + [FieldIdx::new(0), FieldIdx::new(1)] + ); offsets } FieldsShape::Primitive @@ -1434,7 +1423,7 @@ impl LayoutCalculator { Ok(LayoutData { variants: Variants::Single { index: VariantIdx::new(0) }, - fields: FieldsShape::Arbitrary { offsets, memory_index }, + fields: FieldsShape::Arbitrary { offsets, in_memory_order }, backend_repr: abi, largest_niche, uninhabited, @@ -1530,7 +1519,10 @@ where Ok(LayoutData { variants: Variants::Single { index: VariantIdx::new(0) }, - fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }, + fields: FieldsShape::Arbitrary { + offsets: [Size::ZERO].into(), + in_memory_order: [FieldIdx::new(0)].into(), + }, backend_repr: repr, largest_niche: elt.largest_niche, uninhabited: false, diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs index 2b22276d4aed..815cf1e28a08 100644 --- a/compiler/rustc_abi/src/layout/coroutine.rs +++ b/compiler/rustc_abi/src/layout/coroutine.rs @@ -182,33 +182,29 @@ pub(super) fn layout< // CoroutineLayout. debug!("prefix = {:#?}", prefix); let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields { - FieldsShape::Arbitrary { mut offsets, memory_index } => { - let mut inverse_memory_index = memory_index.invert_bijective_mapping(); - + FieldsShape::Arbitrary { mut offsets, in_memory_order } => { // "a" (`0..b_start`) and "b" (`b_start..`) correspond to // "outer" and "promoted" fields respectively. let b_start = tag_index.plus(1); let offsets_b = IndexVec::from_raw(offsets.raw.split_off(b_start.index())); let offsets_a = offsets; - // Disentangle the "a" and "b" components of `inverse_memory_index` + // Disentangle the "a" and "b" components of `in_memory_order` // by preserving the order but keeping only one disjoint "half" each. // FIXME(eddyb) build a better abstraction for permutations, if possible. - let inverse_memory_index_b: IndexVec = inverse_memory_index - .iter() - .filter_map(|&i| i.index().checked_sub(b_start.index()).map(FieldIdx::new)) - .collect(); - inverse_memory_index.raw.retain(|&i| i.index() < b_start.index()); - let inverse_memory_index_a = inverse_memory_index; - - // Since `inverse_memory_index_{a,b}` each only refer to their - // respective fields, they can be safely inverted - let memory_index_a = inverse_memory_index_a.invert_bijective_mapping(); - let memory_index_b = inverse_memory_index_b.invert_bijective_mapping(); + let mut in_memory_order_a = IndexVec::::new(); + let mut in_memory_order_b = IndexVec::::new(); + for i in in_memory_order { + if let Some(j) = i.index().checked_sub(b_start.index()) { + in_memory_order_b.push(FieldIdx::new(j)); + } else { + in_memory_order_a.push(i); + } + } let outer_fields = - FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a }; - (outer_fields, offsets_b, memory_index_b) + FieldsShape::Arbitrary { offsets: offsets_a, in_memory_order: in_memory_order_a }; + (outer_fields, offsets_b, in_memory_order_b.invert_bijective_mapping()) } _ => unreachable!(), }; @@ -236,7 +232,7 @@ pub(super) fn layout< )?; variant.variants = Variants::Single { index }; - let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else { + let FieldsShape::Arbitrary { offsets, in_memory_order } = variant.fields else { unreachable!(); }; @@ -249,8 +245,9 @@ pub(super) fn layout< // promoted fields were being used, but leave the elements not in the // subset as `invalid_field_idx`, which we can filter out later to // obtain a valid (bijective) mapping. + let memory_index = in_memory_order.invert_bijective_mapping(); let invalid_field_idx = promoted_memory_index.len() + memory_index.len(); - let mut combined_inverse_memory_index = + let mut combined_in_memory_order = IndexVec::from_elem_n(FieldIdx::new(invalid_field_idx), invalid_field_idx); let mut offsets_and_memory_index = iter::zip(offsets, memory_index); @@ -268,19 +265,18 @@ pub(super) fn layout< (promoted_offsets[field_idx], promoted_memory_index[field_idx]) } }; - combined_inverse_memory_index[memory_index] = i; + combined_in_memory_order[memory_index] = i; offset }) .collect(); - // Remove the unused slots and invert the mapping to obtain the - // combined `memory_index` (also see previous comment). - combined_inverse_memory_index.raw.retain(|&i| i.index() != invalid_field_idx); - let combined_memory_index = combined_inverse_memory_index.invert_bijective_mapping(); + // Remove the unused slots to obtain the combined `in_memory_order` + // (also see previous comment). + combined_in_memory_order.raw.retain(|&i| i.index() != invalid_field_idx); variant.fields = FieldsShape::Arbitrary { offsets: combined_offsets, - memory_index: combined_memory_index, + in_memory_order: combined_in_memory_order, }; size = size.max(variant.size); diff --git a/compiler/rustc_abi/src/layout/simple.rs b/compiler/rustc_abi/src/layout/simple.rs index b3807c872739..3784611b157b 100644 --- a/compiler/rustc_abi/src/layout/simple.rs +++ b/compiler/rustc_abi/src/layout/simple.rs @@ -16,7 +16,7 @@ impl LayoutData { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets: IndexVec::new(), - memory_index: IndexVec::new(), + in_memory_order: IndexVec::new(), }, backend_repr: BackendRepr::Memory { sized }, largest_niche: None, @@ -108,7 +108,7 @@ impl LayoutData { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldsShape::Arbitrary { offsets: [Size::ZERO, b_offset].into(), - memory_index: [0, 1].into(), + in_memory_order: [FieldIdx::new(0), FieldIdx::new(1)].into(), }, backend_repr: BackendRepr::ScalarPair(a, b), largest_niche, @@ -133,7 +133,7 @@ impl LayoutData { Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), - memory_index: IndexVec::new(), + in_memory_order: IndexVec::new(), }, }, backend_repr: BackendRepr::Memory { sized: true }, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 53b2c3f36dfc..061ad8617893 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1636,19 +1636,14 @@ pub enum FieldsShape { // FIXME(eddyb) use small vector optimization for the common case. offsets: IndexVec, - /// Maps source order field indices to memory order indices, + /// Maps memory order field indices to source order indices, /// depending on how the fields were reordered (if at all). /// This is a permutation, with both the source order and the /// memory order using the same (0..n) index ranges. /// - /// Note that during computation of `memory_index`, sometimes - /// it is easier to operate on the inverse mapping (that is, - /// from memory order to source order), and that is usually - /// named `inverse_memory_index`. - /// // FIXME(eddyb) build a better abstraction for permutations, if possible. // FIXME(camlorn) also consider small vector optimization here. - memory_index: IndexVec, + in_memory_order: IndexVec, }, } @@ -1682,51 +1677,17 @@ impl FieldsShape { } } - #[inline] - pub fn memory_index(&self, i: usize) -> usize { - match *self { - FieldsShape::Primitive => { - unreachable!("FieldsShape::memory_index: `Primitive`s have no fields") - } - FieldsShape::Union(_) | FieldsShape::Array { .. } => i, - FieldsShape::Arbitrary { ref memory_index, .. } => { - memory_index[FieldIdx::new(i)].try_into().unwrap() - } - } - } - /// Gets source indices of the fields by increasing offsets. #[inline] pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator { - let mut inverse_small = [0u8; 64]; - let mut inverse_big = IndexVec::new(); - let use_small = self.count() <= inverse_small.len(); - - // We have to write this logic twice in order to keep the array small. - if let FieldsShape::Arbitrary { ref memory_index, .. } = *self { - if use_small { - for (field_idx, &mem_idx) in memory_index.iter_enumerated() { - inverse_small[mem_idx as usize] = field_idx.index() as u8; - } - } else { - inverse_big = memory_index.invert_bijective_mapping(); - } - } - // Primitives don't really have fields in the way that structs do, // but having this return an empty iterator for them is unhelpful // since that makes them look kinda like ZSTs, which they're not. let pseudofield_count = if let FieldsShape::Primitive = self { 1 } else { self.count() }; - (0..pseudofield_count).map(move |i| match *self { + (0..pseudofield_count).map(move |i| match self { FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i, - FieldsShape::Arbitrary { .. } => { - if use_small { - inverse_small[i] as usize - } else { - inverse_big[i as u32].index() - } - } + FieldsShape::Arbitrary { in_memory_order, .. } => in_memory_order[i as u32].index(), }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index e59f70877c94..c68c66b27185 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -690,6 +690,16 @@ impl SingleAttributeParser for SanitizeParser { } } +pub(crate) struct ThreadLocalParser; + +impl NoArgsAttributeParser for ThreadLocalParser { + const PATH: &[Symbol] = &[sym::thread_local]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ThreadLocal; +} + pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser; impl NoArgsAttributeParser for RustcPassIndirectlyInNonRusticAbisParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index a752869c2eb2..df4970d8aa90 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -23,7 +23,7 @@ use crate::attributes::codegen_attrs::{ ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser, NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser, - TrackCallerParser, UsedParser, + ThreadLocalParser, TrackCallerParser, UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::crate_level::{ @@ -269,6 +269,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 80f1098de85e..6ed70b39c5b7 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1275,29 +1275,81 @@ impl<'tcx> RegionInferenceContext<'tcx> { shorter_fr: RegionVid, propagated_outlives_requirements: &mut Option<&mut Vec>>, ) -> RegionRelationCheckResult { - if let Some(propagated_outlives_requirements) = propagated_outlives_requirements - // Shrink `longer_fr` until we find a non-local region (if we do). - // We'll call it `fr-` -- it's ever so slightly smaller than + if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { + // Shrink `longer_fr` until we find some non-local regions. + // We'll call them `longer_fr-` -- they are ever so slightly smaller than // `longer_fr`. - && let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr) - { - debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus); + let longer_fr_minus = self.universal_region_relations.non_local_lower_bounds(longer_fr); + + debug!("try_propagate_universal_region_error: fr_minus={:?}", longer_fr_minus); + + // If we don't find a any non-local regions, we should error out as there is nothing + // to propagate. + if longer_fr_minus.is_empty() { + return RegionRelationCheckResult::Error; + } let blame_constraint = self .best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr) .0; - // Grow `shorter_fr` until we find some non-local regions. (We - // always will.) We'll call them `shorter_fr+` -- they're ever - // so slightly larger than `shorter_fr`. + // Grow `shorter_fr` until we find some non-local regions. + // We will always find at least one: `'static`. We'll call + // them `shorter_fr+` -- they're ever so slightly larger + // than `shorter_fr`. let shorter_fr_plus = self.universal_region_relations.non_local_upper_bounds(shorter_fr); debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus); - for fr in shorter_fr_plus { - // Push the constraint `fr-: shorter_fr+` + + // We then create constraints `longer_fr-: shorter_fr+` that may or may not + // be propagated (see below). + let mut constraints = vec![]; + for fr_minus in longer_fr_minus { + for shorter_fr_plus in &shorter_fr_plus { + constraints.push((fr_minus, *shorter_fr_plus)); + } + } + + // We only need to propagate at least one of the constraints for + // soundness. However, we want to avoid arbitrary choices here + // and currently don't support returning OR constraints. + // + // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`, + // we propagate only those. + // + // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`: + // a --> b --> d + // \ + // \-> c + // Here, `shorter_fr+` of `'a` == `['b, 'c]`. + // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of + // `'d: 'b` and could reject valid code. + // + // So we filter the constraints to regions already outlived by `longer_fr-`, but if + // the filter yields an empty set, we fall back to the original one. + let subset: Vec<_> = constraints + .iter() + .filter(|&&(fr_minus, shorter_fr_plus)| { + self.eval_outlives(fr_minus, shorter_fr_plus) + }) + .copied() + .collect(); + let propagated_constraints = if subset.is_empty() { constraints } else { subset }; + debug!( + "try_propagate_universal_region_error: constraints={:?}", + propagated_constraints + ); + + assert!( + !propagated_constraints.is_empty(), + "Expected at least one constraint to propagate here" + ); + + for (fr_minus, fr_plus) in propagated_constraints { + // Push the constraint `long_fr-: shorter_fr+` propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject: ClosureOutlivesSubject::Region(fr_minus), - outlived_free_region: fr, + outlived_free_region: fr_plus, blame_span: blame_constraint.cause.span, category: blame_constraint.category, }); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index d27a73535bab..279625cb87c9 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -94,28 +94,10 @@ impl UniversalRegionRelations<'_> { /// words, returns the largest (*) known region `fr1` that (a) is /// outlived by `fr` and (b) is not local. /// - /// (*) If there are multiple competing choices, we pick the "postdominating" - /// one. See `TransitiveRelation::postdom_upper_bound` for details. - pub(crate) fn non_local_lower_bound(&self, fr: RegionVid) -> Option { + /// (*) If there are multiple competing choices, we return all of them. + pub(crate) fn non_local_lower_bounds(&self, fr: RegionVid) -> Vec { debug!("non_local_lower_bound(fr={:?})", fr); - let lower_bounds = self.non_local_bounds(&self.outlives, fr); - - // In case we find more than one, reduce to one for - // convenience. This is to prevent us from generating more - // complex constraints, but it will cause spurious errors. - let post_dom = self.outlives.mutual_immediate_postdominator(lower_bounds); - - debug!("non_local_bound: post_dom={:?}", post_dom); - - post_dom.and_then(|post_dom| { - // If the mutual immediate postdom is not local, then - // there is no non-local result we can return. - if !self.universal_regions.is_local_free_region(post_dom) { - Some(post_dom) - } else { - None - } - }) + self.non_local_bounds(&self.outlives, fr) } /// Helper for `non_local_upper_bounds` and `non_local_lower_bounds`. diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 2878fa7aa298..65779b38ad1c 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -10,7 +10,7 @@ //! function u0:22(i64) -> i8, i8 system_v { //! ; symbol _ZN97_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$RF$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17hd361e9f5c3d1c4deE //! ; instance Instance { def: Item(DefId(0:42 ~ example[3895]::{impl#0}::call_once)), args: ['{erased}, '{erased}] } -//! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: Memory { sized: true }, fields: Arbitrary { offsets: [], memory_index: [] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 12266848898570219025 } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } +//! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: Memory { sized: true }, fields: Arbitrary { offsets: [], in_memory_order: [] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 12266848898570219025 } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], in_memory_order: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } //! //! ; kind loc.idx param pass mode ty //! ; ssa _0 (u8, u8) 2b 1 var=(0, 1) @@ -41,7 +41,7 @@ //! ; //! ; _0 = >::call_mut(move _3, copy _2) //! v2 = stack_load.i64 ss0 -//! ; abi: FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: &mut IsNotEmpty, layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(1 bytes)) }) }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } +//! ; abi: FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: &mut IsNotEmpty, layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(1 bytes)) }) }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, backend_repr: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(8 bytes), randomization_seed: 281492156579847 } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, backend_repr: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], in_memory_order: [0, 1] }, largest_niche: None, uninhabited: false, variants: Single { index: 0 }, max_repr_align: None, unadjusted_abi_align: Align(1 bytes), randomization_seed: 71776127651151873 } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } //! v3, v4 = call fn0(v1, v2) ; v1 = 1 //! v5 -> v3 //! v6 -> v4 diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 18da945f5a31..1afb087178f1 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -707,8 +707,7 @@ pub(crate) unsafe fn llvm_optimize( if cgcx.target_is_like_gpu && config.offload.contains(&config::Offload::Enable) { let cx = SimpleCx::new(module.module_llvm.llmod(), module.module_llvm.llcx, cgcx.pointer_size); - // For now we only support up to 10 kernels named kernel_0 ... kernel_9, a follow-up PR is - // introducing a proper offload intrinsic to solve this limitation. + for func in cx.get_functions() { let offload_kernel = "offload-kernel"; if attributes::has_string_attr(func, offload_kernel) { diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 6cbddfec4631..16455b4c79cd 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -23,13 +23,14 @@ use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::TyCtxt; -use rustc_session::config::DebugInfo; +use rustc_session::config::{DebugInfo, Offload}; use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; use super::ModuleLlvm; use crate::attributes; use crate::builder::Builder; +use crate::builder::gpu_offload::OffloadGlobals; use crate::context::CodegenCx; use crate::llvm::{self, Value}; @@ -85,6 +86,19 @@ pub(crate) fn compile_codegen_unit( let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str()); { let mut cx = CodegenCx::new(tcx, cgu, &llvm_module); + + // Declare and store globals shared by all offload kernels + // + // These globals are left in the LLVM-IR host module so all kernels can access them. + // They are necessary for correct offload execution. We do this here to simplify the + // `offload` intrinsic, avoiding the need for tracking whether it's the first + // intrinsic call or not. + if cx.sess().opts.unstable_opts.offload.contains(&Offload::Enable) + && !cx.sess().target.is_like_gpu + { + cx.offload_globals.replace(Some(OffloadGlobals::declare(&cx))); + } + let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx); for &(mono_item, data) in &mono_items { mono_item.predefine::>( diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 5d1ddd057d88..046501d08c48 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -2,17 +2,76 @@ use std::ffi::CString; use llvm::Linkage::*; use rustc_abi::Align; -use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_middle::ty::offload_meta::OffloadMetadata; -use crate::builder::SBuilder; +use crate::builder::Builder; +use crate::common::CodegenCx; use crate::llvm::AttributePlace::Function; -use crate::llvm::{self, BasicBlock, Linkage, Type, Value}; +use crate::llvm::{self, Linkage, Type, Value}; use crate::{SimpleCx, attributes}; +// LLVM kernel-independent globals required for offloading +pub(crate) struct OffloadGlobals<'ll> { + pub launcher_fn: &'ll llvm::Value, + pub launcher_ty: &'ll llvm::Type, + + pub bin_desc: &'ll llvm::Type, + + pub kernel_args_ty: &'ll llvm::Type, + + pub offload_entry_ty: &'ll llvm::Type, + + pub begin_mapper: &'ll llvm::Value, + pub end_mapper: &'ll llvm::Value, + pub mapper_fn_ty: &'ll llvm::Type, + + pub ident_t_global: &'ll llvm::Value, + + pub register_lib: &'ll llvm::Value, + pub unregister_lib: &'ll llvm::Value, + pub init_rtls: &'ll llvm::Value, +} + +impl<'ll> OffloadGlobals<'ll> { + pub(crate) fn declare(cx: &CodegenCx<'ll, '_>) -> Self { + let (launcher_fn, launcher_ty) = generate_launcher(cx); + let kernel_args_ty = KernelArgsTy::new_decl(cx); + let offload_entry_ty = TgtOffloadEntry::new_decl(cx); + let (begin_mapper, _, end_mapper, mapper_fn_ty) = gen_tgt_data_mappers(cx); + let ident_t_global = generate_at_one(cx); + + let tptr = cx.type_ptr(); + let ti32 = cx.type_i32(); + let tgt_bin_desc_ty = vec![ti32, tptr, tptr, tptr]; + let bin_desc = cx.type_named_struct("struct.__tgt_bin_desc"); + cx.set_struct_body(bin_desc, &tgt_bin_desc_ty, false); + + let register_lib = declare_offload_fn(&cx, "__tgt_register_lib", mapper_fn_ty); + let unregister_lib = declare_offload_fn(&cx, "__tgt_unregister_lib", mapper_fn_ty); + let init_ty = cx.type_func(&[], cx.type_void()); + let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); + + OffloadGlobals { + launcher_fn, + launcher_ty, + bin_desc, + kernel_args_ty, + offload_entry_ty, + begin_mapper, + end_mapper, + mapper_fn_ty, + ident_t_global, + register_lib, + unregister_lib, + init_rtls, + } + } +} + // ; Function Attrs: nounwind // declare i32 @__tgt_target_kernel(ptr, i64, i32, i32, ptr, ptr) #2 -fn generate_launcher<'ll>(cx: &'ll SimpleCx<'_>) -> (&'ll llvm::Value, &'ll llvm::Type) { +fn generate_launcher<'ll>(cx: &CodegenCx<'ll, '_>) -> (&'ll llvm::Value, &'ll llvm::Type) { let tptr = cx.type_ptr(); let ti64 = cx.type_i64(); let ti32 = cx.type_i32(); @@ -30,7 +89,7 @@ fn generate_launcher<'ll>(cx: &'ll SimpleCx<'_>) -> (&'ll llvm::Value, &'ll llvm // @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @0 }, align 8 // FIXME(offload): @0 should include the file name (e.g. lib.rs) in which the function to be // offloaded was defined. -fn generate_at_one<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Value { +pub(crate) fn generate_at_one<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll llvm::Value { let unknown_txt = ";unknown;unknown;0;0;;"; let c_entry_name = CString::new(unknown_txt).unwrap(); let c_val = c_entry_name.as_bytes_with_nul(); @@ -68,7 +127,7 @@ pub(crate) struct TgtOffloadEntry { } impl TgtOffloadEntry { - pub(crate) fn new_decl<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Type { + pub(crate) fn new_decl<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll llvm::Type { let offload_entry_ty = cx.type_named_struct("struct.__tgt_offload_entry"); let tptr = cx.type_ptr(); let ti64 = cx.type_i64(); @@ -82,7 +141,7 @@ impl TgtOffloadEntry { } fn new<'ll>( - cx: &'ll SimpleCx<'_>, + cx: &CodegenCx<'ll, '_>, region_id: &'ll Value, llglobal: &'ll Value, ) -> [&'ll Value; 9] { @@ -126,7 +185,7 @@ impl KernelArgsTy { const OFFLOAD_VERSION: u64 = 3; const FLAGS: u64 = 0; const TRIPCOUNT: u64 = 0; - fn new_decl<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll Type { + fn new_decl<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Type { let kernel_arguments_ty = cx.type_named_struct("struct.__tgt_kernel_arguments"); let tptr = cx.type_ptr(); let ti64 = cx.type_i64(); @@ -140,8 +199,8 @@ impl KernelArgsTy { kernel_arguments_ty } - fn new<'ll>( - cx: &'ll SimpleCx<'_>, + fn new<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, num_args: u64, memtransfer_types: &'ll Value, geps: [&'ll Value; 3], @@ -171,7 +230,8 @@ impl KernelArgsTy { } // Contains LLVM values needed to manage offloading for a single kernel. -pub(crate) struct OffloadKernelData<'ll> { +#[derive(Copy, Clone)] +pub(crate) struct OffloadKernelGlobals<'ll> { pub offload_sizes: &'ll llvm::Value, pub memtransfer_types: &'ll llvm::Value, pub region_id: &'ll llvm::Value, @@ -179,7 +239,7 @@ pub(crate) struct OffloadKernelData<'ll> { } fn gen_tgt_data_mappers<'ll>( - cx: &'ll SimpleCx<'_>, + cx: &CodegenCx<'ll, '_>, ) -> (&'ll llvm::Value, &'ll llvm::Value, &'ll llvm::Value, &'ll llvm::Type) { let tptr = cx.type_ptr(); let ti64 = cx.type_i64(); @@ -241,12 +301,18 @@ pub(crate) fn add_global<'ll>( // mapped to/from the gpu. It also returns a region_id with the name of this kernel, to be // concatenated into the list of region_ids. pub(crate) fn gen_define_handling<'ll>( - cx: &SimpleCx<'ll>, - offload_entry_ty: &'ll llvm::Type, + cx: &CodegenCx<'ll, '_>, metadata: &[OffloadMetadata], - types: &[&Type], - symbol: &str, -) -> OffloadKernelData<'ll> { + types: &[&'ll Type], + symbol: String, + offload_globals: &OffloadGlobals<'ll>, +) -> OffloadKernelGlobals<'ll> { + if let Some(entry) = cx.offload_kernel_cache.borrow().get(&symbol) { + return *entry; + } + + let offload_entry_ty = offload_globals.offload_entry_ty; + // It seems like non-pointer values are automatically mapped. So here, we focus on pointer (or // reference) types. let ptr_meta = types.iter().zip(metadata).filter_map(|(&x, meta)| match cx.type_kind(x) { @@ -272,9 +338,9 @@ pub(crate) fn gen_define_handling<'ll>( let name = format!(".{symbol}.region_id"); let initializer = cx.get_const_i8(0); - let region_id = add_unnamed_global(&cx, &name, initializer, WeakAnyLinkage); + let region_id = add_global(&cx, &name, initializer, WeakAnyLinkage); - let c_entry_name = CString::new(symbol).unwrap(); + let c_entry_name = CString::new(symbol.clone()).unwrap(); let c_val = c_entry_name.as_bytes_with_nul(); let offload_entry_name = format!(".offloading.entry_name.{symbol}"); @@ -298,11 +364,16 @@ pub(crate) fn gen_define_handling<'ll>( let c_section_name = CString::new("llvm_offload_entries").unwrap(); llvm::set_section(offload_entry, &c_section_name); - OffloadKernelData { offload_sizes, memtransfer_types, region_id, offload_entry } + let result = + OffloadKernelGlobals { offload_sizes, memtransfer_types, region_id, offload_entry }; + + cx.offload_kernel_cache.borrow_mut().insert(symbol, result); + + result } fn declare_offload_fn<'ll>( - cx: &'ll SimpleCx<'_>, + cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll llvm::Type, ) -> &'ll llvm::Value { @@ -335,28 +406,28 @@ fn declare_offload_fn<'ll>( // 4. set insert point after kernel call. // 5. generate all the GEPS and stores, to be used in 6) // 6. generate __tgt_target_data_end calls to move data from the GPU -pub(crate) fn gen_call_handling<'ll>( - cx: &SimpleCx<'ll>, - bb: &BasicBlock, - offload_data: &OffloadKernelData<'ll>, +pub(crate) fn gen_call_handling<'ll, 'tcx>( + builder: &mut Builder<'_, 'll, 'tcx>, + offload_data: &OffloadKernelGlobals<'ll>, args: &[&'ll Value], types: &[&Type], metadata: &[OffloadMetadata], + offload_globals: &OffloadGlobals<'ll>, ) { - let OffloadKernelData { offload_sizes, offload_entry, memtransfer_types, region_id } = + let cx = builder.cx; + let OffloadKernelGlobals { offload_sizes, offload_entry, memtransfer_types, region_id } = offload_data; - let (tgt_decl, tgt_target_kernel_ty) = generate_launcher(&cx); + + let tgt_decl = offload_globals.launcher_fn; + let tgt_target_kernel_ty = offload_globals.launcher_ty; + // %struct.__tgt_bin_desc = type { i32, ptr, ptr, ptr } - let tptr = cx.type_ptr(); - let ti32 = cx.type_i32(); - let tgt_bin_desc_ty = vec![ti32, tptr, tptr, tptr]; - let tgt_bin_desc = cx.type_named_struct("struct.__tgt_bin_desc"); - cx.set_struct_body(tgt_bin_desc, &tgt_bin_desc_ty, false); + let tgt_bin_desc = offload_globals.bin_desc; - let tgt_kernel_decl = KernelArgsTy::new_decl(&cx); - let (begin_mapper_decl, _, end_mapper_decl, fn_ty) = gen_tgt_data_mappers(&cx); - - let mut builder = SBuilder::build(cx, bb); + let tgt_kernel_decl = offload_globals.kernel_args_ty; + let begin_mapper_decl = offload_globals.begin_mapper; + let end_mapper_decl = offload_globals.end_mapper; + let fn_ty = offload_globals.mapper_fn_ty; let num_args = types.len() as u64; let ip = unsafe { llvm::LLVMRustGetInsertPoint(&builder.llbuilder) }; @@ -378,9 +449,8 @@ pub(crate) fn gen_call_handling<'ll>( // Step 0) // %struct.__tgt_bin_desc = type { i32, ptr, ptr, ptr } // %6 = alloca %struct.__tgt_bin_desc, align 8 - let llfn = unsafe { llvm::LLVMGetBasicBlockParent(bb) }; unsafe { - llvm::LLVMRustPositionBuilderPastAllocas(&builder.llbuilder, llfn); + llvm::LLVMRustPositionBuilderPastAllocas(&builder.llbuilder, builder.llfn()); } let tgt_bin_desc_alloca = builder.direct_alloca(tgt_bin_desc, Align::EIGHT, "EmptyDesc"); @@ -413,16 +483,16 @@ pub(crate) fn gen_call_handling<'ll>( } let mapper_fn_ty = cx.type_func(&[cx.type_ptr()], cx.type_void()); - let register_lib_decl = declare_offload_fn(&cx, "__tgt_register_lib", mapper_fn_ty); - let unregister_lib_decl = declare_offload_fn(&cx, "__tgt_unregister_lib", mapper_fn_ty); + let register_lib_decl = offload_globals.register_lib; + let unregister_lib_decl = offload_globals.unregister_lib; let init_ty = cx.type_func(&[], cx.type_void()); - let init_rtls_decl = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); + let init_rtls_decl = offload_globals.init_rtls; // FIXME(offload): Later we want to add them to the wrapper code, rather than our main function. // call void @__tgt_register_lib(ptr noundef %6) - builder.call(mapper_fn_ty, register_lib_decl, &[tgt_bin_desc_alloca], None); + builder.call(mapper_fn_ty, None, None, register_lib_decl, &[tgt_bin_desc_alloca], None, None); // call void @__tgt_init_all_rtls() - builder.call(init_ty, init_rtls_decl, &[], None); + builder.call(init_ty, None, None, init_rtls_decl, &[], None, None); for i in 0..num_args { let idx = cx.get_const_i32(i); @@ -437,15 +507,15 @@ pub(crate) fn gen_call_handling<'ll>( // For now we have a very simplistic indexing scheme into our // offload_{baseptrs,ptrs,sizes}. We will probably improve this along with our gpu frontend pr. - fn get_geps<'a, 'll>( - builder: &mut SBuilder<'a, 'll>, - cx: &'ll SimpleCx<'ll>, + fn get_geps<'ll, 'tcx>( + builder: &mut Builder<'_, 'll, 'tcx>, ty: &'ll Type, ty2: &'ll Type, a1: &'ll Value, a2: &'ll Value, a4: &'ll Value, ) -> [&'ll Value; 3] { + let cx = builder.cx; let i32_0 = cx.get_const_i32(0); let gep1 = builder.inbounds_gep(ty, a1, &[i32_0, i32_0]); @@ -454,9 +524,8 @@ pub(crate) fn gen_call_handling<'ll>( [gep1, gep2, gep3] } - fn generate_mapper_call<'a, 'll>( - builder: &mut SBuilder<'a, 'll>, - cx: &'ll SimpleCx<'ll>, + fn generate_mapper_call<'ll, 'tcx>( + builder: &mut Builder<'_, 'll, 'tcx>, geps: [&'ll Value; 3], o_type: &'ll Value, fn_to_call: &'ll Value, @@ -464,20 +533,20 @@ pub(crate) fn gen_call_handling<'ll>( num_args: u64, s_ident_t: &'ll Value, ) { + let cx = builder.cx; let nullptr = cx.const_null(cx.type_ptr()); let i64_max = cx.get_const_i64(u64::MAX); let num_args = cx.get_const_i32(num_args); let args = vec![s_ident_t, i64_max, num_args, geps[0], geps[1], geps[2], o_type, nullptr, nullptr]; - builder.call(fn_ty, fn_to_call, &args, None); + builder.call(fn_ty, None, None, fn_to_call, &args, None, None); } // Step 2) - let s_ident_t = generate_at_one(&cx); - let geps = get_geps(&mut builder, &cx, ty, ty2, a1, a2, a4); + let s_ident_t = offload_globals.ident_t_global; + let geps = get_geps(builder, ty, ty2, a1, a2, a4); generate_mapper_call( - &mut builder, - &cx, + builder, geps, memtransfer_types, begin_mapper_decl, @@ -504,14 +573,13 @@ pub(crate) fn gen_call_handling<'ll>( region_id, a5, ]; - builder.call(tgt_target_kernel_ty, tgt_decl, &args, None); + builder.call(tgt_target_kernel_ty, None, None, tgt_decl, &args, None, None); // %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args) // Step 4) - let geps = get_geps(&mut builder, &cx, ty, ty2, a1, a2, a4); + let geps = get_geps(builder, ty, ty2, a1, a2, a4); generate_mapper_call( - &mut builder, - &cx, + builder, geps, memtransfer_types, end_mapper_decl, @@ -520,7 +588,5 @@ pub(crate) fn gen_call_handling<'ll>( s_ident_t, ); - builder.call(mapper_fn_ty, unregister_lib_decl, &[tgt_bin_desc_alloca], None); - - drop(builder); + builder.call(mapper_fn_ty, None, None, unregister_lib_decl, &[tgt_bin_desc_alloca], None, None); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6caf60e3cc41..03da70d48f7d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -35,6 +35,7 @@ use smallvec::SmallVec; use crate::abi::to_llvm_calling_convention; use crate::back::write::to_llvm_code_model; +use crate::builder::gpu_offload::{OffloadGlobals, OffloadKernelGlobals}; use crate::callee::get_fn; use crate::debuginfo::metadata::apply_vcall_visibility_metadata; use crate::llvm::{self, Metadata, MetadataKindId, Module, Type, Value}; @@ -156,6 +157,12 @@ pub(crate) struct FullCx<'ll, 'tcx> { /// Cache of Objective-C selector references pub objc_selrefs: RefCell>, + + /// Globals shared by the offloading runtime + pub offload_globals: RefCell>>, + + /// Cache of kernel-specific globals + pub offload_kernel_cache: RefCell>>, } fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { @@ -639,6 +646,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { objc_class_t: Cell::new(None), objc_classrefs: Default::default(), objc_selrefs: Default::default(), + offload_globals: Default::default(), + offload_kernel_cache: Default::default(), }, PhantomData, ) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 82615d4a160e..3bc890310cc8 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -26,7 +26,7 @@ use tracing::debug; use crate::abi::FnAbiLlvmExt; use crate::builder::Builder; use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call}; -use crate::builder::gpu_offload::TgtOffloadEntry; +use crate::builder::gpu_offload::{gen_call_handling, gen_define_handling}; use crate::context::CodegenCx; use crate::errors::{ AutoDiffWithoutEnable, AutoDiffWithoutLto, OffloadWithoutEnable, OffloadWithoutFatLTO, @@ -1295,8 +1295,6 @@ fn codegen_offload<'ll, 'tcx>( let args = get_args_from_tuple(bx, args[1], fn_target); let target_symbol = symbol_name_for_instance_in_crate(tcx, fn_target, LOCAL_CRATE); - let offload_entry_ty = TgtOffloadEntry::new_decl(&cx); - let sig = tcx.fn_sig(fn_target.def_id()).skip_binder().skip_binder(); let inputs = sig.inputs(); @@ -1304,17 +1302,16 @@ fn codegen_offload<'ll, 'tcx>( let types = inputs.iter().map(|ty| cx.layout_of(*ty).llvm_type(cx)).collect::>(); - let offload_data = crate::builder::gpu_offload::gen_define_handling( - cx, - offload_entry_ty, - &metadata, - &types, - &target_symbol, - ); - - // FIXME(Sa4dUs): pass the original builder once we separate kernel launch logic from globals - let bb = unsafe { llvm::LLVMGetInsertBlock(bx.llbuilder) }; - crate::builder::gpu_offload::gen_call_handling(cx, bb, &offload_data, &args, &types, &metadata); + let offload_globals_ref = cx.offload_globals.borrow(); + let offload_globals = match offload_globals_ref.as_ref() { + Some(globals) => globals, + None => { + // Offload is not initialized, cannot continue + return; + } + }; + let offload_data = gen_define_handling(&cx, &metadata, &types, target_symbol, offload_globals); + gen_call_handling(bx, &offload_data, &args, &types, &metadata, offload_globals); } fn get_args_from_tuple<'ll, 'tcx>( diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 473598bad394..8135fd43dd93 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -350,6 +350,9 @@ fn process_builtin_attrs( codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM; } } + AttributeKind::ThreadLocal => { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL + } _ => {} } } @@ -366,7 +369,6 @@ fn process_builtin_attrs( sym::rustc_allocator_zeroed => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } - sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::instruction_set => { codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr) } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 88a116094758..9a4b9786eb15 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -561,8 +561,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable }, )?; // Sanity-check that `eval_fn_call` either pushed a new frame or - // did a jump to another block. - if self.frame_idx() == old_stack && self.frame().loc == old_loc { + // did a jump to another block. We disable the sanity check for functions that + // can't return, since Miri sometimes does have to keep the location the same + // for those (which is fine since execution will continue on a different thread). + if target.is_some() && self.frame_idx() == old_stack && self.frame().loc == old_loc + { span_bug!(terminator.source_info.span, "evaluating this call made no progress"); } } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index b5de10c7dcd1..95106c7c143b 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use rustc_abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; -use rustc_index::IndexVec; +use rustc_index::{Idx as _, IndexVec}; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, Ty}; use tracing::trace; @@ -27,13 +27,15 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { /// This function provides the chance to reorder the order in which fields are visited for /// `FieldsShape::Aggregate`. /// - /// The default means we iterate in source declaration order; alternatively this can do some - /// work with `memory_index` to iterate in memory order. + /// The default means we iterate in source declaration order; alternatively this can use + /// `in_memory_order` to iterate in memory order. #[inline(always)] fn aggregate_field_iter( - memory_index: &IndexVec, - ) -> impl Iterator + 'static { - memory_index.indices() + in_memory_order: &IndexVec, + ) -> impl Iterator { + // Allow the optimizer to elide the bounds checking when creating each index. + let _ = FieldIdx::new(in_memory_order.len()); + (0..in_memory_order.len()).map(FieldIdx::new) } // Recursive actions, ready to be overloaded. @@ -168,8 +170,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { &FieldsShape::Union(fields) => { self.visit_union(v, fields)?; } - FieldsShape::Arbitrary { memory_index, .. } => { - for idx in Self::aggregate_field_iter(memory_index) { + FieldsShape::Arbitrary { in_memory_order, .. } => { + for idx in Self::aggregate_field_iter(in_memory_order) { let field = self.ecx().project_field(v, idx)?; self.visit_field(v, idx.as_usize(), &field)?; } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 0b930dc342f2..a7e8515e415f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1123,7 +1123,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word, List: &[r#""...""#]), DuplicatesOk, EncodeCrossCrate::Yes, ), - rustc_attr!( + rustc_attr!( rustc_offload_kernel, Normal, template!(Word), DuplicatesOk, EncodeCrossCrate::Yes, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 1a382d8f124b..e9f9b2445deb 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1010,6 +1010,9 @@ pub enum AttributeKind { /// `#[unsafe(force_target_feature(enable = "...")]`. TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool }, + /// Represents `#[thread_local]` + ThreadLocal, + /// Represents `#[track_caller]` TrackCaller(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 7c1e71f258be..68456dfe4c29 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -114,6 +114,7 @@ impl AttributeKind { Stability { .. } => Yes, StdInternalSymbol(..) => No, TargetFeature { .. } => No, + ThreadLocal => No, TrackCaller(..) => Yes, TypeConst(..) => Yes, TypeLengthLimit { .. } => No, diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs index d2702bdb0571..415fe370b702 100644 --- a/compiler/rustc_index/src/slice.rs +++ b/compiler/rustc_index/src/slice.rs @@ -181,9 +181,6 @@ impl IndexSlice { /// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`, /// assuming the values in `self` are a permutation of `0..self.len()`. /// - /// This is used to go between `memory_index` (source field order to memory order) - /// and `inverse_memory_index` (memory order to source field order). - /// See also `FieldsShape::Arbitrary::memory_index` for more details. // FIXME(eddyb) build a better abstraction for permutations, if possible. pub fn invert_bijective_mapping(&self) -> IndexVec { debug_assert_eq!( diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index abfd078f7462..af8ff5643f2c 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -251,9 +251,7 @@ impl<'a> MissingNativeLibrary<'a> { // if it looks like the user has provided a complete filename rather just the bare lib name, // then provide a note that they might want to try trimming the name let suggested_name = if !verbatim { - if let Some(libname) = libname.strip_prefix("lib") - && let Some(libname) = libname.strip_suffix(".a") - { + if let Some(libname) = libname.strip_circumfix("lib", ".a") { // this is a unix style filename so trim prefix & suffix Some(libname) } else if let Some(libname) = libname.strip_suffix(".lib") { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index f31c4938e118..f3b738f93d2d 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(proc_macro_internals)] #![feature(result_option_map_or_default)] +#![feature(strip_circumfix)] #![feature(trusted_len)] // tidy-alphabetical-end diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c0106ea0c627..cf069b364be8 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -484,10 +484,6 @@ passes_sanitize_attribute_not_allowed = .no_body = function has no body .help = sanitize attribute can be applied to a function (with body), impl block, or module -passes_should_be_applied_to_static = - attribute should be applied to a static - .label = not a static - passes_should_be_applied_to_trait = attribute should be applied to a trait .label = not a trait diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 945dcec798e3..7822614a05cb 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -297,6 +297,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::PinV2(..) | AttributeKind::WindowsSubsystem(..) + | AttributeKind::ThreadLocal ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -310,7 +311,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_const, ..] => { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } - [sym::thread_local, ..] => self.check_thread_local(attr, span, target), [sym::rustc_clean, ..] | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] @@ -768,19 +768,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if the `#[thread_local]` attribute on `item` is valid. - fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) { - match target { - Target::ForeignStatic | Target::Static => {} - _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToStatic { - attr_span: attr.span(), - defn_span: span, - }); - } - } - } - fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) { if let Some(location) = match target { Target::AssocTy => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4f97f74c7804..2b817c6dd106 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -98,15 +98,6 @@ pub(crate) struct AttrShouldBeAppliedToTrait { pub defn_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_static)] -pub(crate) struct AttrShouldBeAppliedToStatic { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, -} - #[derive(Diagnostic)] #[diag(passes_doc_alias_bad_location)] pub(crate) struct DocAliasBadLocation<'a> { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 49b2e0c1ff1a..3d641905d325 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -241,12 +241,14 @@ bitflags::bitflags! { } impl Encodable for RemapPathScopeComponents { + #[inline] fn encode(&self, s: &mut E) { s.emit_u8(self.bits()); } } impl Decodable for RemapPathScopeComponents { + #[inline] fn decode(s: &mut D) -> RemapPathScopeComponents { RemapPathScopeComponents::from_bits(s.read_u8()) .expect("invalid bits for RemapPathScopeComponents") @@ -308,12 +310,13 @@ struct InnerRealFileName { } impl Hash for RealFileName { + #[inline] fn hash(&self, state: &mut H) { // To prevent #70924 from happening again we should only hash the // remapped path if that exists. This is because remapped paths to // sysroot crates (/rust/$hash or /rust/$version) remain stable even // if the corresponding local path changes. - if !self.scopes.is_all() { + if !self.was_fully_remapped() { self.local.hash(state); } self.maybe_remapped.hash(state); @@ -327,6 +330,7 @@ impl RealFileName { /// ## Panic /// /// Only one scope components can be given to this function. + #[inline] pub fn path(&self, scope: RemapPathScopeComponents) -> &Path { assert!( scope.bits().count_ones() == 1, @@ -351,6 +355,7 @@ impl RealFileName { /// ## Panic /// /// Only one scope components can be given to this function. + #[inline] pub fn embeddable_name(&self, scope: RemapPathScopeComponents) -> (&Path, &Path) { assert!( scope.bits().count_ones() == 1, @@ -369,26 +374,58 @@ impl RealFileName { /// if this information exists. /// /// May not exists if the filename was imported from another crate. + /// + /// Avoid embedding this in build artifacts; prefer `path()` or `embeddable_name()`. + #[inline] pub fn local_path(&self) -> Option<&Path> { - self.local.as_ref().map(|lp| lp.name.as_ref()) + if self.was_not_remapped() { + Some(&self.maybe_remapped.name) + } else if let Some(local) = &self.local { + Some(&local.name) + } else { + None + } } /// Returns the path suitable for reading from the file system on the local host, /// if this information exists. /// /// May not exists if the filename was imported from another crate. + /// + /// Avoid embedding this in build artifacts; prefer `path()` or `embeddable_name()`. + #[inline] pub fn into_local_path(self) -> Option { - self.local.map(|lp| lp.name) + if self.was_not_remapped() { + Some(self.maybe_remapped.name) + } else if let Some(local) = self.local { + Some(local.name) + } else { + None + } } /// Returns whenever the filename was remapped. + #[inline] pub(crate) fn was_remapped(&self) -> bool { !self.scopes.is_empty() } + /// Returns whenever the filename was fully remapped. + #[inline] + fn was_fully_remapped(&self) -> bool { + self.scopes.is_all() + } + + /// Returns whenever the filename was not remapped. + #[inline] + fn was_not_remapped(&self) -> bool { + self.scopes.is_empty() + } + /// Returns an empty `RealFileName` /// /// Useful as the working directory input to `SourceMap::to_real_filename`. + #[inline] pub fn empty() -> RealFileName { RealFileName { local: Some(InnerRealFileName { @@ -420,9 +457,14 @@ impl RealFileName { /// Update the filename for encoding in the crate metadata. /// /// Currently it's about removing the local part when the filename - /// is fully remapped. + /// is either fully remapped or not remapped at all. + #[inline] pub fn update_for_crate_metadata(&mut self) { - if self.scopes.is_all() { + if self.was_fully_remapped() || self.was_not_remapped() { + // NOTE: This works because when the filename is fully + // remapped, we don't care about the `local` part, + // and when the filename is not remapped at all, + // `maybe_remapped` and `local` are equal. self.local = None; } } @@ -529,6 +571,7 @@ impl FileName { /// if this information exists. /// /// Avoid embedding this in build artifacts. Prefer using the `display` method. + #[inline] pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> { FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped } } @@ -537,16 +580,19 @@ impl FileName { /// if this information exists. /// /// Avoid embedding this in build artifacts. Prefer using the `display` method. + #[inline] pub fn prefer_local_unconditionally(&self) -> FileNameDisplay<'_> { FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local } } /// Returns a short (either the filename or an empty string). + #[inline] pub fn short(&self) -> FileNameDisplay<'_> { FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Short } } /// Returns a `Display`-able path for the given scope. + #[inline] pub fn display(&self, scope: RemapPathScopeComponents) -> FileNameDisplay<'_> { FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Scope(scope) } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 3d500694c978..b06339f59425 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2956,11 +2956,6 @@ impl Target { matches!(self.linker_flavor, LinkerFlavor::Bpf), "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`" ); - check_eq!( - self.arch == Arch::Nvptx64, - matches!(self.linker_flavor, LinkerFlavor::Ptx), - "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`" - ); for args in [ &self.pre_link_args, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 69a65e6b0f02..47775f968400 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a".into(), + features: "+v8a,+outline-atomics".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs index 35003c4d4dd6..be09681b1f35 100644 --- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs @@ -19,9 +19,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { os: Os::Cuda, vendor: "nvidia".into(), - linker_flavor: LinkerFlavor::Ptx, - // The linker can be installed from `crates.io`. - linker: Some("rust-ptx-linker".into()), + linker_flavor: LinkerFlavor::Llbc, // With `ptx-linker` approach, it can be later overridden via link flags. cpu: "sm_30".into(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 32be23eed765..4de3ba3e2781 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1758,8 +1758,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // specify a byte literal (ty::Uint(ty::UintTy::U8), ty::Char) => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) - && let Some(code) = - code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) + && let Some(code) = code.strip_circumfix('\'', '\'') // forbid all Unicode escapes && !code.starts_with("\\u") // forbids literal Unicode characters beyond ASCII @@ -1776,7 +1775,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // specify a character literal (issue #92479) (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) - && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) + && let Some(code) = code.strip_circumfix('"', '"') && code.chars().count() == 1 { suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral { diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 0184b2ccde78..6705d271bc7d 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -22,6 +22,7 @@ #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] #![feature(never_type)] +#![feature(strip_circumfix)] #![feature(try_blocks)] #![feature(unwrap_infallible)] #![feature(yeet_expr)] diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index d9ebdadf3b79..1202ed238431 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -491,7 +491,7 @@ pub(crate) mod rustc { ) -> Result { // This constructor does not support non-`FieldsShape::Arbitrary` // layouts. - let FieldsShape::Arbitrary { offsets, memory_index } = layout.fields() else { + let FieldsShape::Arbitrary { offsets, in_memory_order } = layout.fields() else { return Err(Err::NotYetSupported); }; @@ -519,8 +519,7 @@ pub(crate) mod rustc { } // Append the fields, in memory order, to the layout. - let inverse_memory_index = memory_index.invert_bijective_mapping(); - for &field_idx in inverse_memory_index.iter() { + for &field_idx in in_memory_order.iter() { // Add interfield padding. let padding_needed = offsets[field_idx] - size; let padding = Self::padding(padding_needed.bytes_usize()); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 6962eeddf137..62f3667ad7f4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -9,7 +9,7 @@ use rustc_abi::{ use rustc_hashes::Hash64; use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; -use rustc_index::IndexVec; +use rustc_index::{Idx as _, IndexVec}; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; @@ -374,7 +374,7 @@ fn layout_of_uncached<'tcx>( // specifically care about pattern types will have to handle it. layout.fields = FieldsShape::Arbitrary { offsets: [Size::ZERO].into_iter().collect(), - memory_index: [0].into_iter().collect(), + in_memory_order: [FieldIdx::new(0)].into_iter().collect(), }; tcx.mk_layout(layout) } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 0abf5eff7f2f..7ca6ae46a8f8 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -722,7 +722,6 @@ impl Step for Miri { // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", &host_sysroot); - cargo.env("MIRI", &miri.tool_path); // Set the target. cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 36598982481b..0eb7e1d84bd0 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -12,7 +12,7 @@ platform. ## Requirements -This target is `no_std` and will typically be built with crate-type `cdylib` and `-C linker-flavor=llbc`, which generates PTX. +This target is `no_std`, and uses the `llvm-bitcode-linker` by default. For PTX output, build with crate-type `cdylib`. The necessary components for this workflow are: - `rustup toolchain add nightly` @@ -38,7 +38,7 @@ While the compiler accepts `#[target_feature(enable = "ptx80", enable = "sm_89") A `no_std` crate containing one or more functions with `extern "ptx-kernel"` can be compiled to PTX using a command like the following. ```console -$ RUSTFLAGS='-Ctarget-cpu=sm_89' cargo +nightly rustc --target=nvptx64-nvidia-cuda -Zbuild-std=core --crate-type=cdylib -- -Clinker-flavor=llbc -Zunstable-options +$ RUSTFLAGS='-Ctarget-cpu=sm_89' cargo +nightly rustc --target=nvptx64-nvidia-cuda -Zbuild-std=core --crate-type=cdylib ``` Intrinsics in `core::arch::nvptx` may use `#[cfg(target_feature = "...")]`, thus it's necessary to use `-Zbuild-std=core` with appropriate `RUSTFLAGS`. The following components are needed for this workflow: diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index ee71564a1417..4d9e352595a1 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -14,7 +14,7 @@ use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; -use rustc_span::{BytePos, FileName, Symbol}; +use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Symbol}; use tracing::info; use super::print_item::{full_path, print_item, print_item_path}; @@ -365,7 +365,10 @@ impl<'tcx> Context<'tcx> { // We can safely ignore synthetic `SourceFile`s. let file = match span.filename(self.sess()) { - FileName::Real(ref path) => path.local_path()?.to_path_buf(), + FileName::Real(ref path) => path + .local_path() + .unwrap_or(path.path(RemapPathScopeComponents::MACRO)) + .to_path_buf(), _ => return None, }; let file = &file; @@ -499,10 +502,12 @@ impl<'tcx> Context<'tcx> { } = options; let src_root = match krate.src(tcx) { - FileName::Real(ref p) => match p.local_path().map(|p| p.parent()).flatten() { - Some(p) => p.to_path_buf(), - None => PathBuf::new(), - }, + FileName::Real(ref p) => { + match p.local_path().unwrap_or(p.path(RemapPathScopeComponents::MACRO)).parent() { + Some(p) => p.to_path_buf(), + None => PathBuf::new(), + } + } _ => PathBuf::new(), }; // If user passed in `--playground-url` arg, we fill in crate name here diff --git a/src/tools/cargo b/src/tools/cargo index e91b2baa632c..3861f60f6b58 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit e91b2baa632c0c7e84216c91ecfe107c37d887c1 +Subproject commit 3861f60f6b58f57524c0e7aab1f5c1ad83e35409 diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index f11860f4a1ad..218e4ffe5e2f 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -584,10 +584,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } fn aggregate_field_iter( - memory_index: &IndexVec, - ) -> impl Iterator + 'static { - let inverse_memory_index = memory_index.invert_bijective_mapping(); - inverse_memory_index.into_iter() + in_memory_order: &IndexVec, + ) -> impl Iterator { + in_memory_order.iter().copied() } // Hook to detect `UnsafeCell`. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 74ae93348d58..571f5efc9739 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -538,7 +538,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { code, crate::concurrency::ExitType::ExitCalled, )?; - todo!(); // FIXME(genmc): Add a way to return here that is allowed to not do progress (can't use existing EmulateItemResult variants). + return interp_ok(EmulateItemResult::AlreadyJumped); } throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false }); } diff --git a/src/tools/miri/tests/genmc/fail/shims/exit.rs b/src/tools/miri/tests/genmc/fail/shims/exit.rs new file mode 100644 index 000000000000..4138f4e785bb --- /dev/null +++ b/src/tools/miri/tests/genmc/fail/shims/exit.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Zmiri-genmc -Zmiri-disable-stacked-borrows + +fn main() { + std::thread::spawn(|| { + unsafe { std::hint::unreachable_unchecked() }; //~ERROR: entering unreachable code + }); + // If we exit immediately, we might entirely miss the UB in the other thread. + std::process::exit(0); +} diff --git a/src/tools/miri/tests/genmc/fail/shims/exit.stderr b/src/tools/miri/tests/genmc/fail/shims/exit.stderr new file mode 100644 index 000000000000..dead5faaa514 --- /dev/null +++ b/src/tools/miri/tests/genmc/fail/shims/exit.stderr @@ -0,0 +1,126 @@ +Running GenMC Verification... +warning: GenMC currently does not model spurious failures of `compare_exchange_weak`. Miri with GenMC might miss bugs related to spurious failures. + --> RUSTLIB/std/src/thread/mod.rs:LL:CC + | +LL | match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GenMC might miss possible behaviors of this code + | + = note: BACKTRACE: + = note: inside `std::thread::ThreadId::new` at RUSTLIB/std/src/thread/mod.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/thread/current.rs:LL:CC + = note: inside `std::thread::current::id::get_or_init` at RUSTLIB/std/src/thread/current.rs:LL:CC + = note: inside `std::thread::current_id` at RUSTLIB/std/src/thread/current.rs:LL:CC + = note: inside `std::rt::init` at RUSTLIB/std/src/rt.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/rt.rs:LL:CC + = note: inside `std::panicking::catch_unwind::do_call::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panicking.rs:LL:CC + = note: inside `std::panicking::catch_unwind::` at RUSTLIB/std/src/panicking.rs:LL:CC + = note: inside `std::panic::catch_unwind::<{closure@std::rt::lang_start_internal::{closure#0}}, isize>` at RUSTLIB/std/src/panic.rs:LL:CC + = note: inside `std::rt::lang_start_internal` at RUSTLIB/std/src/rt.rs:LL:CC + = note: inside `std::rt::lang_start::<()>` at RUSTLIB/std/src/rt.rs:LL:CC + +warning: GenMC currently does not model the failure ordering for `compare_exchange`. Due to success ordering 'Acquire', the failure ordering 'Relaxed' is treated like 'Acquire'. Miri with GenMC might miss bugs related to this memory access. + --> RUSTLIB/std/src/sys/sync/PLATFORM/futex.rs:LL:CC + | +LL | || self + | ________________^ +LL | | .state +LL | | .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) + | |____________________________________________________________________________________^ GenMC might miss possible behaviors of this code + | + = note: BACKTRACE: + = note: inside `std::sys::sync::PLATFORM::futex::RwLock::read` at RUSTLIB/std/src/sys/sync/PLATFORM/futex.rs:LL:CC + = note: inside `std::sync::RwLock::<()>::read` at RUSTLIB/std/src/sync/poison/rwlock.rs:LL:CC + = note: inside `std::sys::env::PLATFORM::env_read_lock` at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr_stack::>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr::>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::env::PLATFORM::getenv` at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside `std::env::_var_os` at RUSTLIB/std/src/env.rs:LL:CC + = note: inside `std::env::var_os::<&str>` at RUSTLIB/std/src/env.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/thread/mod.rs:LL:CC +note: inside `main` + --> tests/genmc/fail/shims/exit.rs:LL:CC + | +LL | / std::thread::spawn(|| { +LL | | unsafe { std::hint::unreachable_unchecked() }; +LL | | }); + | |______^ + +warning: GenMC currently does not model spurious failures of `compare_exchange_weak`. Miri with GenMC might miss bugs related to spurious failures. + --> RUSTLIB/std/src/sys/sync/PLATFORM/futex.rs:LL:CC + | +LL | || self + | ________________^ +LL | | .state +LL | | .compare_exchange_weak(state, state + READ_LOCKED, Acquire, Relaxed) + | |____________________________________________________________________________________^ GenMC might miss possible behaviors of this code + | + = note: BACKTRACE: + = note: inside `std::sys::sync::PLATFORM::futex::RwLock::read` at RUSTLIB/std/src/sys/sync/PLATFORM/futex.rs:LL:CC + = note: inside `std::sync::RwLock::<()>::read` at RUSTLIB/std/src/sync/poison/rwlock.rs:LL:CC + = note: inside `std::sys::env::PLATFORM::env_read_lock` at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr_stack::>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::pal::PLATFORM::small_c_string::run_with_cstr::>` at RUSTLIB/std/src/sys/pal/PLATFORM/small_c_string.rs:LL:CC + = note: inside `std::sys::env::PLATFORM::getenv` at RUSTLIB/std/src/sys/env/PLATFORM.rs:LL:CC + = note: inside `std::env::_var_os` at RUSTLIB/std/src/env.rs:LL:CC + = note: inside `std::env::var_os::<&str>` at RUSTLIB/std/src/env.rs:LL:CC + = note: inside closure at RUSTLIB/std/src/thread/mod.rs:LL:CC +note: inside `main` + --> tests/genmc/fail/shims/exit.rs:LL:CC + | +LL | / std::thread::spawn(|| { +LL | | unsafe { std::hint::unreachable_unchecked() }; +LL | | }); + | |______^ + +warning: GenMC currently does not model spurious failures of `compare_exchange_weak`. Miri with GenMC might miss bugs related to spurious failures. + --> RUSTLIB/std/src/rt.rs:LL:CC + | +LL | / CLEANUP.call_once(|| unsafe { +LL | | // Flush stdout and disable buffering. +LL | | crate::io::cleanup(); +... | +LL | | }); + | |______^ GenMC might miss possible behaviors of this code + | + = note: BACKTRACE: + = note: inside `std::rt::cleanup` at RUSTLIB/std/src/rt.rs:LL:CC + = note: inside `std::process::exit` at RUSTLIB/std/src/process.rs:LL:CC +note: inside `main` + --> tests/genmc/fail/shims/exit.rs:LL:CC + | +LL | std::process::exit(0); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: GenMC currently does not model the failure ordering for `compare_exchange`. Due to success ordering 'Acquire', the failure ordering 'Relaxed' is treated like 'Acquire'. Miri with GenMC might miss bugs related to this memory access. + --> RUSTLIB/std/src/sys/exit_guard.rs:LL:CC + | +LL | match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GenMC might miss possible behaviors of this code + | + = note: BACKTRACE: + = note: inside `std::sys::exit_guard::unique_thread_exit` at RUSTLIB/std/src/sys/exit_guard.rs:LL:CC + = note: inside `std::sys::pal::PLATFORM::os::exit` at RUSTLIB/std/src/sys/pal/PLATFORM/os.rs:LL:CC + = note: inside `std::process::exit` at RUSTLIB/std/src/process.rs:LL:CC +note: inside `main` + --> tests/genmc/fail/shims/exit.rs:LL:CC + | +LL | std::process::exit(0); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: Undefined Behavior: entering unreachable code + --> tests/genmc/fail/shims/exit.rs:LL:CC + | +LL | unsafe { std::hint::unreachable_unchecked() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +note: add `-Zmiri-genmc-print-genmc-output` to MIRIFLAGS to see the detailed GenMC error report + +error: aborting due to 1 previous error; 5 warnings emitted + diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index c2cbdd548078..4ef5ce35bd6c 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -27,7 +27,7 @@ enum Mode { } fn miri_path() -> PathBuf { - PathBuf::from(env::var("MIRI").unwrap_or_else(|_| env!("CARGO_BIN_EXE_miri").into())) + env!("CARGO_BIN_EXE_miri").into() } // Build the shared object file for testing native function calls. diff --git a/tests/assembly-llvm/nvptx-arch-default.rs b/tests/assembly-llvm/nvptx-arch-default.rs index a621fd6dcb29..22b4a680e322 100644 --- a/tests/assembly-llvm/nvptx-arch-default.rs +++ b/tests/assembly-llvm/nvptx-arch-default.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib //@ only-nvptx64 #![no_std] diff --git a/tests/assembly-llvm/nvptx-arch-target-cpu.rs b/tests/assembly-llvm/nvptx-arch-target-cpu.rs index 609ab297e636..e02ad0d558a9 100644 --- a/tests/assembly-llvm/nvptx-arch-target-cpu.rs +++ b/tests/assembly-llvm/nvptx-arch-target-cpu.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C target-cpu=sm_50 -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_50 //@ only-nvptx64 #![no_std] diff --git a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs index be98b167470a..6f5ef792e9b3 100644 --- a/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs +++ b/tests/assembly-llvm/nvptx-c-abi-arg-v7.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 // The PTX ABI stability is tied to major versions of the PTX ISA diff --git a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs index c68c71c872c2..02ec9facee7a 100644 --- a/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs +++ b/tests/assembly-llvm/nvptx-c-abi-ret-v7.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 // The PTX ABI stability is tied to major versions of the PTX ISA diff --git a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs index f245b4460f2b..00f6fe9332d9 100644 --- a/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs +++ b/tests/assembly-llvm/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 //@ only-nvptx64 // The following ABI tests are made with nvcc 11.6 does. diff --git a/tests/assembly-llvm/nvptx-safe-naming.rs b/tests/assembly-llvm/nvptx-safe-naming.rs index c70c63b7ee7c..85415b6ca5b5 100644 --- a/tests/assembly-llvm/nvptx-safe-naming.rs +++ b/tests/assembly-llvm/nvptx-safe-naming.rs @@ -1,5 +1,5 @@ //@ assembly-output: ptx-linker -//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc +//@ compile-flags: --crate-type cdylib //@ only-nvptx64 //@ revisions: LLVM20 LLVM21 //@ [LLVM21] min-llvm-version: 21 diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index b0f83c825705..ac179a65828d 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs @@ -11,6 +11,7 @@ // when inside of a function called main. This, too, is a temporary workaround for not having a // frontend. +#![feature(rustc_attrs)] #![feature(core_intrinsics)] #![no_main] @@ -21,29 +22,31 @@ fn main() { core::hint::black_box(&x); } -// CHECK: %struct.__tgt_offload_entry = type { i64, i16, i16, i32, ptr, ptr, i64, i64, ptr } // CHECK: %struct.ident_t = type { i32, i32, i32, i32, ptr } +// CHECK: %struct.__tgt_offload_entry = type { i64, i16, i16, i32, ptr, ptr, i64, i64, ptr } // CHECK: %struct.__tgt_bin_desc = type { i32, ptr, ptr, ptr } // CHECK: %struct.__tgt_kernel_arguments = type { i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, i64, i64, [3 x i32], [3 x i32], i32 } -// CHECK: @.offload_sizes._kernel_1 = private unnamed_addr constant [1 x i64] [i64 1024] -// CHECK: @.offload_maptypes._kernel_1 = private unnamed_addr constant [1 x i64] [i64 35] -// CHECK: @._kernel_1.region_id = internal unnamed_addr constant i8 0 -// CHECK: @.offloading.entry_name._kernel_1 = internal unnamed_addr constant [10 x i8] c"_kernel_1\00", section ".llvm.rodata.offloading", align 1 -// CHECK: @.offloading.entry._kernel_1 = internal constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 1, i32 0, ptr @._kernel_1.region_id, ptr @.offloading.entry_name._kernel_1, i64 0, i64 0, ptr null }, section "llvm_offload_entries", align 8 - // CHECK: @anon.{{.*}}.0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1 // CHECK: @anon.{{.*}}.1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @anon.{{.*}}.0 }, align 8 -// CHECK: Function Attrs: -// CHECK-NEXT: define{{( dso_local)?}} void @main() +// CHECK: @.offload_sizes._kernel_1 = private unnamed_addr constant [1 x i64] [i64 1024] +// CHECK: @.offload_maptypes._kernel_1 = private unnamed_addr constant [1 x i64] [i64 35] +// CHECK: @._kernel_1.region_id = internal constant i8 0 +// CHECK: @.offloading.entry_name._kernel_1 = internal unnamed_addr constant [10 x i8] c"_kernel_1\00", section ".llvm.rodata.offloading", align 1 +// CHECK: @.offloading.entry._kernel_1 = internal constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 1, i32 0, ptr @._kernel_1.region_id, ptr @.offloading.entry_name._kernel_1, i64 0, i64 0, ptr null }, section "llvm_offload_entries", align 8 + +// CHECK: Function Attrs: nounwind +// CHECK: declare i32 @__tgt_target_kernel(ptr, i64, i32, i32, ptr, ptr) + +// CHECK: define{{( dso_local)?}} void @main() // CHECK-NEXT: start: // CHECK-NEXT: %0 = alloca [8 x i8], align 8 // CHECK-NEXT: %x = alloca [1024 x i8], align 16 // CHECK: call void @kernel_1(ptr noalias noundef nonnull align 4 dereferenceable(1024) %x) // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %0) // CHECK-NEXT: store ptr %x, ptr %0, align 8 -// CHECK-NEXT: call void asm sideeffect "", "r,~{memory}"(ptr nonnull %0) #4, !srcloc !4 +// CHECK-NEXT: call void asm sideeffect "", "r,~{memory}"(ptr nonnull %0) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %0) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 1024, ptr nonnull %x) // CHECK-NEXT: ret void @@ -92,9 +95,6 @@ fn main() { // CHECK-NEXT: ret void // CHECK-NEXT: } -// CHECK: Function Attrs: nounwind -// CHECK: declare i32 @__tgt_target_kernel(ptr, i64, i32, i32, ptr, ptr) - #[unsafe(no_mangle)] #[inline(never)] pub fn kernel_1(x: &mut [f32; 256]) { diff --git a/tests/rustdoc/auxiliary/remapped-paths.rs b/tests/rustdoc/auxiliary/remapped-paths.rs new file mode 100644 index 000000000000..f31d2d316f3a --- /dev/null +++ b/tests/rustdoc/auxiliary/remapped-paths.rs @@ -0,0 +1,11 @@ +//@ compile-flags:-Zunstable-options --remap-path-prefix={{src-base}}= + +pub struct MyStruct { + field: u32, +} + +impl MyStruct { + pub fn new() -> MyStruct { + MyStruct { field: 3 } + } +} diff --git a/tests/rustdoc/import-remapped-paths.rs b/tests/rustdoc/import-remapped-paths.rs new file mode 100644 index 000000000000..9e7518f7c017 --- /dev/null +++ b/tests/rustdoc/import-remapped-paths.rs @@ -0,0 +1,19 @@ +// This is a regression for `--remap-path-prefix` in an auxiliary dependency. +// +// We want to make sure that we can still have the "Source" links to the dependency +// even if its paths are remapped. +// +// See also rust-lang/rust#150100 + +//@ aux-build:remapped-paths.rs +//@ build-aux-docs + +#![crate_name = "foo"] + +extern crate remapped_paths; + +//@ has foo/struct.MyStruct.html +//@ has - '//a[@href="../src/remapped_paths/remapped-paths.rs.html#3"]' 'Source' +//@ has - '//a[@href="../src/remapped_paths/remapped-paths.rs.html#8"]' 'Source' + +pub use remapped_paths::MyStruct; diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index d050bfcbaa17..6d2ac90c0c97 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -41,7 +41,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 816addd79576..f297aa984dd2 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 816addd79576..f297aa984dd2 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 816addd79576..f297aa984dd2 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index d050bfcbaa17..6d2ac90c0c97 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -41,7 +41,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 816addd79576..f297aa984dd2 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 04d6f50872a3..8a031b79780a 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -244,7 +244,7 @@ error: fn_abi_of(test_generic) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -328,7 +328,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -400,7 +400,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -479,7 +479,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -552,7 +552,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -629,7 +629,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -701,7 +701,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -779,7 +779,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -851,7 +851,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -962,7 +962,7 @@ error: fn_abi_of(assoc_test) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 85c888c4fae0..00bd3febde4e 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -244,7 +244,7 @@ error: fn_abi_of(test_generic) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -328,7 +328,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -400,7 +400,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -479,7 +479,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -552,7 +552,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -629,7 +629,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -701,7 +701,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -779,7 +779,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -851,7 +851,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -962,7 +962,7 @@ error: fn_abi_of(assoc_test) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 85c888c4fae0..00bd3febde4e 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -244,7 +244,7 @@ error: fn_abi_of(test_generic) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -328,7 +328,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -400,7 +400,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -479,7 +479,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -552,7 +552,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -629,7 +629,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -701,7 +701,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -779,7 +779,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -851,7 +851,7 @@ error: ABIs are not compatible }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -962,7 +962,7 @@ error: fn_abi_of(assoc_test) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index a93982dacfa1..03fe9ea46a4b 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -24,7 +24,7 @@ error: fn_abi_of(extern_c) = FnAbi { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -65,7 +65,7 @@ error: fn_abi_of(extern_c) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -106,7 +106,7 @@ error: fn_abi_of(extern_rust) = FnAbi { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -165,7 +165,7 @@ error: fn_abi_of(extern_rust) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 2233e8e4f623..82d3793c3532 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -41,7 +41,7 @@ error: fn_abi_of(pass_zst) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 228ea12cba8b..d0e5cb631c1e 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -141,12 +141,6 @@ LL | #[forbid(lint1, lint2, ...)] LL | #[forbid(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ -error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:210:1 - | -LL | #[thread_local()] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` - error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/malformed-attrs.rs:105:1 | @@ -618,6 +612,15 @@ LL | #[non_exhaustive = 1] | | didn't expect any arguments here | help: must be of the form: `#[non_exhaustive]` +error[E0565]: malformed `thread_local` attribute input + --> $DIR/malformed-attrs.rs:210:1 + | +LL | #[thread_local()] + | ^^^^^^^^^^^^^^--^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[thread_local]` + error[E0565]: malformed `no_link` attribute input --> $DIR/malformed-attrs.rs:214:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index a86b28d98ecc..584416f58f86 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(take_va_list) = FnAbi { }, fields: Arbitrary { offsets: $OFFSETS, - memory_index: $MEMORY_INDEX, + in_memory_order: $MEMORY_INDEX, }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(take_va_list) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/c-variadic/pass-by-value-abi.rs b/tests/ui/c-variadic/pass-by-value-abi.rs index 1e3935067cc2..a7cf37295a74 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.rs +++ b/tests/ui/c-variadic/pass-by-value-abi.rs @@ -1,7 +1,7 @@ //@ check-fail //@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED" //@ normalize-stderr: "valid_range: 0\.\.=\d+" -> "valid_range: 0..=$$MAX" -//@ normalize-stderr: "memory_index: \[[^\]]+\]" -> "memory_index: $$MEMORY_INDEX" +//@ normalize-stderr: "in_memory_order: \[[^\]]+\]" -> "in_memory_order: $$MEMORY_INDEX" //@ normalize-stderr: "offsets: \[[^\]]+\]" -> "offsets: $$OFFSETS" //@ revisions: x86_64 aarch64 win //@ compile-flags: -O diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr index 8ff93961f667..b8e3f699b30e 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.win.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -20,7 +20,7 @@ error: fn_abi_of(take_va_list) = FnAbi { ), fields: Arbitrary { offsets: $OFFSETS, - memory_index: $MEMORY_INDEX, + in_memory_order: $MEMORY_INDEX, }, largest_niche: None, uninhabited: false, @@ -55,7 +55,7 @@ error: fn_abi_of(take_va_list) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index aafe89d59e33..b5e0e8589af1 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -13,7 +13,7 @@ error: fn_abi_of(take_va_list) = FnAbi { }, fields: Arbitrary { offsets: $OFFSETS, - memory_index: $MEMORY_INDEX, + in_memory_order: $MEMORY_INDEX, }, largest_niche: None, uninhabited: false, @@ -52,7 +52,7 @@ error: fn_abi_of(take_va_list) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -91,7 +91,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { }, fields: Arbitrary { offsets: $OFFSETS, - memory_index: $MEMORY_INDEX, + in_memory_order: $MEMORY_INDEX, }, largest_niche: None, uninhabited: false, @@ -130,7 +130,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -171,7 +171,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { }, fields: Arbitrary { offsets: $OFFSETS, - memory_index: $MEMORY_INDEX, + in_memory_order: $MEMORY_INDEX, }, largest_niche: None, uninhabited: false, @@ -210,7 +210,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/enum-discriminant/wrapping_niche.stderr b/tests/ui/enum-discriminant/wrapping_niche.stderr index e3e1755e14dd..9b97ad4aeac7 100644 --- a/tests/ui/enum-discriminant/wrapping_niche.stderr +++ b/tests/ui/enum-discriminant/wrapping_niche.stderr @@ -16,7 +16,7 @@ error: layout_of(UnsignedAroundZero) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -52,7 +52,7 @@ error: layout_of(UnsignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -73,7 +73,7 @@ error: layout_of(UnsignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -94,7 +94,7 @@ error: layout_of(UnsignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -134,7 +134,7 @@ error: layout_of(SignedAroundZero) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -170,7 +170,7 @@ error: layout_of(SignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -191,7 +191,7 @@ error: layout_of(SignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -212,7 +212,7 @@ error: layout_of(SignedAroundZero) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index b2ce6385ab65..79ce21eb532b 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -16,7 +16,7 @@ error: layout_of(E) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -52,7 +52,7 @@ error: layout_of(E) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -77,7 +77,7 @@ error: layout_of(E) = Layout { Size(4 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, 2, @@ -130,7 +130,7 @@ error: layout_of(S) = Layout { Size(8 bytes), Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, 2, 1, @@ -200,7 +200,7 @@ error: layout_of(Result) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -251,7 +251,7 @@ error: layout_of(Result) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -289,7 +289,7 @@ error: layout_of(Result) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index 659013c8a6f1..20e0a8642a66 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -16,7 +16,7 @@ error: layout_of(A) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -52,7 +52,7 @@ error: layout_of(A) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -92,7 +92,7 @@ error: layout_of(B) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -128,7 +128,7 @@ error: layout_of(B) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -168,7 +168,7 @@ error: layout_of(C) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -204,7 +204,7 @@ error: layout_of(C) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -244,7 +244,7 @@ error: layout_of(P) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -280,7 +280,7 @@ error: layout_of(P) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -320,7 +320,7 @@ error: layout_of(T) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -356,7 +356,7 @@ error: layout_of(T) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 2087fedeb19b..61cfcbdc07f7 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -22,7 +22,7 @@ error: layout_of(MissingPayloadField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -72,7 +72,7 @@ error: layout_of(MissingPayloadField) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -95,7 +95,7 @@ error: layout_of(MissingPayloadField) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -142,7 +142,7 @@ error: layout_of(CommonPayloadField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -193,7 +193,7 @@ error: layout_of(CommonPayloadField) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(CommonPayloadField) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -279,7 +279,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -329,7 +329,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -366,7 +366,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -414,7 +414,7 @@ error: layout_of(NicheFirst) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -470,7 +470,7 @@ error: layout_of(NicheFirst) = Layout { Size(0 bytes), Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -503,7 +503,7 @@ error: layout_of(NicheFirst) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -524,7 +524,7 @@ error: layout_of(NicheFirst) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -570,7 +570,7 @@ error: layout_of(NicheSecond) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -626,7 +626,7 @@ error: layout_of(NicheSecond) = Layout { Size(1 bytes), Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 1, 0, ], @@ -659,7 +659,7 @@ error: layout_of(NicheSecond) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -680,7 +680,7 @@ error: layout_of(NicheSecond) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 6bcc5b4906b5..64e2f42c042f 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -10,7 +10,7 @@ error: layout_of(Aligned1) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -46,7 +46,7 @@ error: layout_of(Aligned1) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -69,7 +69,7 @@ error: layout_of(Aligned1) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -113,7 +113,7 @@ error: layout_of(Aligned2) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -149,7 +149,7 @@ error: layout_of(Aligned2) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -172,7 +172,7 @@ error: layout_of(Aligned2) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 1ef22daf2a9d..a6e603652123 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -16,7 +16,7 @@ error: layout_of(A) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -52,7 +52,7 @@ error: layout_of(A) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -92,7 +92,7 @@ error: layout_of(B) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -128,7 +128,7 @@ error: layout_of(B) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -168,7 +168,7 @@ error: layout_of(C) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -204,7 +204,7 @@ error: layout_of(C) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -244,7 +244,7 @@ error: layout_of(P) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -280,7 +280,7 @@ error: layout_of(P) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -320,7 +320,7 @@ error: layout_of(T) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -356,7 +356,7 @@ error: layout_of(T) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 1707b8aff81c..23f909277808 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -10,7 +10,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -48,7 +48,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -73,7 +73,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -118,7 +118,7 @@ error: layout_of(MultipleAlignments) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -156,7 +156,7 @@ error: layout_of(MultipleAlignments) = Layout { offsets: [ Size(2 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -181,7 +181,7 @@ error: layout_of(MultipleAlignments) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -206,7 +206,7 @@ error: layout_of(MultipleAlignments) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -251,7 +251,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -289,7 +289,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -314,7 +314,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -359,7 +359,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -401,7 +401,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -426,7 +426,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.rs similarity index 66% rename from tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs rename to tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.rs index 5d21fa100a43..addfc7b91391 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs +++ b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.rs @@ -1,6 +1,5 @@ -// Test where we fail to approximate due to demanding a postdom -// relationship between our upper bounds. - +// Test that we can propagate multiple region errors for closure constraints +// where the longer region has multiple non-local lower bounds without any postdominating one. //@ compile-flags:-Zverbose-internals #![feature(rustc_attrs)] @@ -13,9 +12,8 @@ use std::cell::Cell; // 'x: 'b // 'c: 'y // -// we have to prove that `'x: 'y`. We currently can only approximate -// via a postdominator -- hence we fail to choose between `'a` and -// `'b` here and report the error in the closure. +// we have to prove that `'x: 'y`. We find non-local lower bounds of 'x to be 'a and 'b and +// non-local upper bound of 'y to be 'c. So we propagate `'b: 'c` and `'a: 'c`. fn establish_relationships<'a, 'b, 'c, F>( _cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, @@ -36,6 +34,8 @@ fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) #[rustc_regions] fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + //~vv ERROR lifetime may not live long enough + //~v ERROR lifetime may not live long enough establish_relationships( cell_a, cell_b, @@ -43,7 +43,7 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell |_outlives1, _outlives2, _outlives3, x, y| { // Only works if 'x: 'y: let p = x.get(); - demand_y(x, y, p) //~ ERROR + demand_y(x, y, p) }, ); } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr new file mode 100644 index 000000000000..af7ea253cc52 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-both-lower-bounds.stderr @@ -0,0 +1,79 @@ +note: external requirements + --> $DIR/propagate-approximated-both-lower-bounds.rs:43:9 + | +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure args [ + i16, + for extern "rust-call" fn((std::cell::Cell<&'?1 &'^0 u32>, std::cell::Cell<&'?2 &'^0 u32>, std::cell::Cell<&'^1 &'?3 u32>, std::cell::Cell<&'^0 u32>, std::cell::Cell<&'^1 u32>)), + (), + ] + = note: late-bound region is '?7 + = note: late-bound region is '?8 + = note: late-bound region is '?4 + = note: late-bound region is '?5 + = note: late-bound region is '?6 + = note: number of external vids: 7 + = note: where '?2: '?3 + = note: where '?1: '?3 + +note: no external requirements + --> $DIR/propagate-approximated-both-lower-bounds.rs:36:1 + | +LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error: lifetime may not live long enough + --> $DIR/propagate-approximated-both-lower-bounds.rs:39:5 + | +LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +... +LL | / establish_relationships( +LL | | cell_a, +LL | | cell_b, +LL | | cell_c, +... | +LL | | }, +LL | | ); + | |_____^ argument requires that `'a` must outlive `'c` + | + = help: consider adding the following bound: `'a: 'c` + = note: requirement occurs because of the type `Cell<&'?10 u32>`, which makes the generic argument `&'?10 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/propagate-approximated-both-lower-bounds.rs:39:5 + | +LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'b` defined here +... +LL | / establish_relationships( +LL | | cell_a, +LL | | cell_b, +LL | | cell_c, +... | +LL | | }, +LL | | ); + | |_____^ argument requires that `'b` must outlive `'c` + | + = help: consider adding the following bound: `'b: 'c` + = note: requirement occurs because of the type `Cell<&'?10 u32>`, which makes the generic argument `&'?10 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +help: the following changes may resolve your lifetime errors + | + = help: add bound `'a: 'c` + = help: add bound `'b: 'c` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr deleted file mode 100644 index 134ce99014d8..000000000000 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ /dev/null @@ -1,42 +0,0 @@ -note: no external requirements - --> $DIR/propagate-approximated-fail-no-postdom.rs:43:9 - | -LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: defining type: supply::{closure#0} with closure args [ - i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &'^0 u32>, std::cell::Cell<&'?2 &'^0 u32>, std::cell::Cell<&'^1 &'?3 u32>, std::cell::Cell<&'^0 u32>, std::cell::Cell<&'^1 u32>)), - (), - ] - = note: late-bound region is '?7 - = note: late-bound region is '?8 - = note: late-bound region is '?4 - = note: late-bound region is '?5 - = note: late-bound region is '?6 - -error: lifetime may not live long enough - --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13 - | -LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ---------- ---------- has type `Cell<&'2 &'?3 u32>` - | | - | has type `Cell<&'?1 &'1 u32>` -... -LL | demand_y(x, y, p) - | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` - | - = note: requirement occurs because of the type `Cell<&'?34 u32>`, which makes the generic argument `&'?34 u32` invariant - = note: the struct `Cell` is invariant over the parameter `T` - = help: see for more information about variance - -note: no external requirements - --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1 - | -LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: defining type: supply - -error: aborting due to 1 previous error - diff --git a/tests/ui/regions/closure-prop-issue-104477-case1.rs b/tests/ui/regions/closure-prop-issue-104477-case1.rs new file mode 100644 index 000000000000..307ca930baea --- /dev/null +++ b/tests/ui/regions/closure-prop-issue-104477-case1.rs @@ -0,0 +1,14 @@ +//@ check-pass +// This checks that the compiler does not require that 'a: 'b. '_ has 'a and 'b as non-local +// upper bounds, but the compiler should not propagate 'a: 'b OR 'b: 'a when checking +// the closures. If it did, this would fail to compile, eventhough it's a valid program. +// PR #148329 explains this in detail. + +struct MyTy<'x, 'a, 'b>(std::cell::Cell<(&'x &'a u8, &'x &'b u8)>); +fn wf(_: T) {} +fn test<'a, 'b>() { + |_: &'a u8, x: MyTy<'_, 'a, 'b>| wf(x); + |x: MyTy<'_, 'a, 'b>, _: &'a u8| wf(x); +} + +fn main(){} diff --git a/tests/ui/regions/closure-prop-issue-104477-case2.rs b/tests/ui/regions/closure-prop-issue-104477-case2.rs new file mode 100644 index 000000000000..a77a11d0eceb --- /dev/null +++ b/tests/ui/regions/closure-prop-issue-104477-case2.rs @@ -0,0 +1,12 @@ +//@ check-pass +// This test checks that the compiler propagates outlives requirements for both +// non-local lower bounds ['a, 'b] of '_, instead of conservatively finding a post-dominiting one +// from those 2. + +struct MyTy<'a, 'b, 'x>(std::cell::Cell<(&'a &'x str, &'b &'x str)>); +fn wf(_: T) {} +fn test<'a, 'b, 'x>() { + |x: MyTy<'a, 'b, '_>| wf(x); +} + +fn main() {} diff --git a/tests/ui/regions/closure-prop-issue-148289.rs b/tests/ui/regions/closure-prop-issue-148289.rs new file mode 100644 index 000000000000..7f89927a76e0 --- /dev/null +++ b/tests/ui/regions/closure-prop-issue-148289.rs @@ -0,0 +1,26 @@ +//@ check-pass +// This test checks that the compiler does not propagate 'd: 'c when propagating region errors +// for the closure argument. If it did, this would fail to compile, eventhough it's a valid program. +// It should only propagate 'd: 'b. +// PR #148329 explains this in detail. + +#[derive(Clone, Copy)] +struct Inv<'a>(*mut &'a ()); +impl<'a> Inv<'a> { + fn outlived_by<'b: 'a>(self, _: Inv<'b>) {} +} +struct OutlivedBy<'a, 'b: 'a>(Inv<'a>, Inv<'b>); + +fn closure_arg<'b, 'c, 'd>( + _: impl for<'a> FnOnce(Inv<'a>, OutlivedBy<'a, 'b>, OutlivedBy<'a, 'c>, Inv<'d>), +) { +} +fn foo<'b, 'c, 'd: 'b>() { + closure_arg::<'b, 'c, 'd>(|a, b, c, d| { + a.outlived_by(b.1); + a.outlived_by(c.1); + b.1.outlived_by(d); + }); +} + +fn main() {} diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 1a1929c530ff..62f6ec92d493 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -16,7 +16,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -60,7 +60,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -108,7 +108,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -158,7 +158,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -195,7 +195,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -270,7 +270,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { Size(8 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -298,7 +298,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index 67729e9fcef9..3e0efad974cd 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -16,7 +16,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -60,7 +60,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -108,7 +108,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -158,7 +158,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -195,7 +195,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -270,7 +270,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { Size(8 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -298,7 +298,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 1a1929c530ff..62f6ec92d493 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -16,7 +16,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -60,7 +60,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -108,7 +108,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -158,7 +158,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -195,7 +195,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -270,7 +270,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { Size(8 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -298,7 +298,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 1a1929c530ff..62f6ec92d493 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -16,7 +16,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -60,7 +60,7 @@ error: layout_of(Univariant) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -108,7 +108,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -158,7 +158,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -195,7 +195,7 @@ error: layout_of(TwoVariants) = Layout { offsets: [ Size(4 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -270,7 +270,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { Size(8 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -298,7 +298,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { offsets: [ Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index d88a842f8848..b25e4a9b7b6f 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -16,7 +16,7 @@ error: layout_of(UnivariantU8) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -60,7 +60,7 @@ error: layout_of(UnivariantU8) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -108,7 +108,7 @@ error: layout_of(TwoVariantsU8) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -158,7 +158,7 @@ error: layout_of(TwoVariantsU8) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -195,7 +195,7 @@ error: layout_of(TwoVariantsU8) = Layout { offsets: [ Size(1 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -231,7 +231,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -270,7 +270,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { Size(8 bytes), Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, 1, ], @@ -298,7 +298,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { offsets: [ Size(8 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/thread-local/non-static.rs b/tests/ui/thread-local/non-static.rs index f1c4273870bf..f14ff20f449b 100644 --- a/tests/ui/thread-local/non-static.rs +++ b/tests/ui/thread-local/non-static.rs @@ -2,19 +2,19 @@ #![feature(thread_local)] #[thread_local] -//~^ ERROR attribute should be applied to a static +//~^ ERROR `#[thread_local]` attribute cannot be used on constants const A: u32 = 0; #[thread_local] -//~^ ERROR attribute should be applied to a static +//~^ ERROR `#[thread_local]` attribute cannot be used on functions fn main() { #[thread_local] || {}; - //~^ ERROR attribute should be applied to a static + //~^ ERROR `#[thread_local]` attribute cannot be used on closures } struct S { #[thread_local] - //~^ ERROR attribute should be applied to a static + //~^ ERROR `#[thread_local]` attribute cannot be used on struct fields a: String, b: String, } diff --git a/tests/ui/thread-local/non-static.stderr b/tests/ui/thread-local/non-static.stderr index 09a1618d6e71..c83a6beb4c6a 100644 --- a/tests/ui/thread-local/non-static.stderr +++ b/tests/ui/thread-local/non-static.stderr @@ -1,38 +1,34 @@ -error: attribute should be applied to a static +error: `#[thread_local]` attribute cannot be used on constants --> $DIR/non-static.rs:4:1 | LL | #[thread_local] | ^^^^^^^^^^^^^^^ -LL | -LL | const A: u32 = 0; - | ----------------- not a static + | + = help: `#[thread_local]` can be applied to foreign statics and statics -error: attribute should be applied to a static +error: `#[thread_local]` attribute cannot be used on functions --> $DIR/non-static.rs:8:1 | -LL | #[thread_local] - | ^^^^^^^^^^^^^^^ -LL | -LL | / fn main() { -LL | | #[thread_local] || {}; -LL | | -LL | | } - | |_- not a static +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ + | + = help: `#[thread_local]` can be applied to foreign statics and statics -error: attribute should be applied to a static +error: `#[thread_local]` attribute cannot be used on closures --> $DIR/non-static.rs:11:5 | LL | #[thread_local] || {}; - | ^^^^^^^^^^^^^^^ ----- not a static + | ^^^^^^^^^^^^^^^ + | + = help: `#[thread_local]` can be applied to foreign statics and statics -error: attribute should be applied to a static +error: `#[thread_local]` attribute cannot be used on struct fields --> $DIR/non-static.rs:16:5 | LL | #[thread_local] | ^^^^^^^^^^^^^^^ -LL | -LL | a: String, - | --------- not a static + | + = help: `#[thread_local]` can be applied to foreign statics and statics error: aborting due to 4 previous errors diff --git a/tests/ui/type/pattern_types/non_null.stderr b/tests/ui/type/pattern_types/non_null.stderr index ad61e9a59147..0847af2d086f 100644 --- a/tests/ui/type/pattern_types/non_null.stderr +++ b/tests/ui/type/pattern_types/non_null.stderr @@ -17,7 +17,7 @@ error: layout_of((*const T) is !null) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -64,7 +64,7 @@ error: layout_of(Option<(*const ()) is !null>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -96,7 +96,7 @@ error: layout_of(Option<(*const ()) is !null>) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -126,7 +126,7 @@ error: layout_of(Option<(*const ()) is !null>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -186,7 +186,7 @@ error: layout_of((*const [u8]) is !null) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/type/pattern_types/or_patterns.stderr b/tests/ui/type/pattern_types/or_patterns.stderr index adc7320829b9..7206c570187b 100644 --- a/tests/ui/type/pattern_types/or_patterns.stderr +++ b/tests/ui/type/pattern_types/or_patterns.stderr @@ -57,7 +57,7 @@ error: layout_of((i8) is (i8::MIN..=-1 | 1..)) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -102,7 +102,7 @@ error: layout_of((i8) is (i8::MIN..=-2 | 0..)) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index c9a846e22f58..6c9acac7eb7b 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -16,7 +16,7 @@ error: layout_of(NonZero) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -61,7 +61,7 @@ error: layout_of((u32) is 1..) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -106,7 +106,7 @@ error: layout_of(Option<(u32) is 1..>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -137,7 +137,7 @@ error: layout_of(Option<(u32) is 1..>) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -166,7 +166,7 @@ error: layout_of(Option<(u32) is 1..>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -217,7 +217,7 @@ error: layout_of(Option>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -248,7 +248,7 @@ error: layout_of(Option>) = Layout { }, fields: Arbitrary { offsets: [], - memory_index: [], + in_memory_order: [], }, largest_niche: None, uninhabited: false, @@ -277,7 +277,7 @@ error: layout_of(Option>) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -328,7 +328,7 @@ error: layout_of(NonZeroU32New) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -401,7 +401,7 @@ error: layout_of((i8) is -10..=10) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], }, @@ -446,7 +446,7 @@ error: layout_of((i8) is i8::MIN..=0) = Layout { offsets: [ Size(0 bytes), ], - memory_index: [ + in_memory_order: [ 0, ], },