Merge ref 'cb79c42008' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref:cb79c42008Filtered ref: 3d67cb5b8f2db0234afa897808f69bf76143044e Upstream diff:f51d1bcdc6...cb79c42008This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
346e02a75a
91 changed files with 934 additions and 580 deletions
|
|
@ -714,7 +714,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
},
|
||||
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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
let pair =
|
||||
LayoutData::<FieldIdx, VariantIdx>::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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
},
|
||||
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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
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<u32, FieldIdx> = fields.indices().collect();
|
||||
let mut in_memory_order: IndexVec<u32, FieldIdx> = 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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
// 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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
|
||||
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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
let pair =
|
||||
LayoutData::<FieldIdx, VariantIdx>::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<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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<u32, FieldIdx> = 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::<u32, FieldIdx>::new();
|
||||
let mut in_memory_order_b = IndexVec::<u32, FieldIdx>::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);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
|
|||
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<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
|
|||
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<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
|
|||
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 },
|
||||
|
|
|
|||
|
|
@ -1636,19 +1636,14 @@ pub enum FieldsShape<FieldIdx: Idx> {
|
|||
// FIXME(eddyb) use small vector optimization for the common case.
|
||||
offsets: IndexVec<FieldIdx, Size>,
|
||||
|
||||
/// 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<FieldIdx, u32>,
|
||||
in_memory_order: IndexVec<u32, FieldIdx>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1682,51 +1677,17 @@ impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[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<Item = usize> {
|
||||
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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -690,6 +690,16 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ThreadLocalParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ThreadLocalParser {
|
||||
const PATH: &[Symbol] = &[sym::thread_local];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisParser {
|
||||
|
|
|
|||
|
|
@ -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<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<ThreadLocalParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
Single<WithoutArgs<TypeConstParser>>,
|
||||
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
||||
|
|
|
|||
|
|
@ -1275,29 +1275,81 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
shorter_fr: RegionVid,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
|
||||
) -> 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,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<RegionVid> {
|
||||
/// (*) If there are multiple competing choices, we return all of them.
|
||||
pub(crate) fn non_local_lower_bounds(&self, fr: RegionVid) -> Vec<RegionVid> {
|
||||
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`.
|
||||
|
|
|
|||
|
|
@ -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 = <IsNotEmpty as mini_core::FnMut<(&&[u16],)>>::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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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::<Builder<'_, '_, '_>>(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<FxHashMap<Symbol, &'ll Value>>,
|
||||
|
||||
/// Globals shared by the offloading runtime
|
||||
pub offload_globals: RefCell<Option<OffloadGlobals<'ll>>>,
|
||||
|
||||
/// Cache of kernel-specific globals
|
||||
pub offload_kernel_cache: RefCell<FxHashMap<String, OffloadKernelGlobals<'ll>>>,
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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::<Vec<_>>();
|
||||
|
||||
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>(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<FieldIdx, u32>,
|
||||
) -> impl Iterator<Item = FieldIdx> + 'static {
|
||||
memory_index.indices()
|
||||
in_memory_order: &IndexVec<u32, FieldIdx>,
|
||||
) -> impl Iterator<Item = FieldIdx> {
|
||||
// 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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ impl AttributeKind {
|
|||
Stability { .. } => Yes,
|
||||
StdInternalSymbol(..) => No,
|
||||
TargetFeature { .. } => No,
|
||||
ThreadLocal => No,
|
||||
TrackCaller(..) => Yes,
|
||||
TypeConst(..) => Yes,
|
||||
TypeLengthLimit { .. } => No,
|
||||
|
|
|
|||
|
|
@ -181,9 +181,6 @@ impl<I: Idx, J: Idx> IndexSlice<I, J> {
|
|||
/// 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<J, I> {
|
||||
debug_assert_eq!(
|
||||
|
|
|
|||
|
|
@ -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") {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -241,12 +241,14 @@ bitflags::bitflags! {
|
|||
}
|
||||
|
||||
impl<E: Encoder> Encodable<E> for RemapPathScopeComponents {
|
||||
#[inline]
|
||||
fn encode(&self, s: &mut E) {
|
||||
s.emit_u8(self.bits());
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> 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<H: std::hash::Hasher>(&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<PathBuf> {
|
||||
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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ pub(crate) mod rustc {
|
|||
) -> Result<Self, Err> {
|
||||
// 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());
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e91b2baa632c0c7e84216c91ecfe107c37d887c1
|
||||
Subproject commit 3861f60f6b58f57524c0e7aab1f5c1ad83e35409
|
||||
|
|
@ -584,10 +584,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
|
||||
fn aggregate_field_iter(
|
||||
memory_index: &IndexVec<FieldIdx, u32>,
|
||||
) -> impl Iterator<Item = FieldIdx> + 'static {
|
||||
let inverse_memory_index = memory_index.invert_bijective_mapping();
|
||||
inverse_memory_index.into_iter()
|
||||
in_memory_order: &IndexVec<u32, FieldIdx>,
|
||||
) -> impl Iterator<Item = FieldIdx> {
|
||||
in_memory_order.iter().copied()
|
||||
}
|
||||
|
||||
// Hook to detect `UnsafeCell`.
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
|||
9
src/tools/miri/tests/genmc/fail/shims/exit.rs
Normal file
9
src/tools/miri/tests/genmc/fail/shims/exit.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
126
src/tools/miri/tests/genmc/fail/shims/exit.stderr
Normal file
126
src/tools/miri/tests/genmc/fail/shims/exit.stderr
Normal file
|
|
@ -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::<isize, {closure@std::rt::lang_start_internal::{closure#0}}>` 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::<std::option::Option<std::ffi::OsString>>` 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::<std::option::Option<std::ffi::OsString>>` 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::<std::option::Option<std::ffi::OsString>>` 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::<std::option::Option<std::ffi::OsString>>` 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
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
|
|
|
|||
11
tests/rustdoc/auxiliary/remapped-paths.rs
Normal file
11
tests/rustdoc/auxiliary/remapped-paths.rs
Normal file
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
19
tests/rustdoc/import-remapped-paths.rs
Normal file
19
tests/rustdoc/import-remapped-paths.rs
Normal file
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<i32, i32>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -251,7 +251,7 @@ error: layout_of(Result<i32, i32>) = Layout {
|
|||
offsets: [
|
||||
Size(4 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -289,7 +289,7 @@ error: layout_of(Result<i32, i32>) = Layout {
|
|||
offsets: [
|
||||
Size(4 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<NonZero<u16>>>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -289,7 +289,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
|
|||
offsets: [
|
||||
Size(4 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -314,7 +314,7 @@ error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
|
|||
offsets: [
|
||||
Size(1 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -359,7 +359,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -401,7 +401,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -426,7 +426,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -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<Region(BrAnon), Region(BrAnon)> 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<T>` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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<T>` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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
|
||||
|
||||
|
|
@ -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<Region(BrAnon), Region(BrAnon)> 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<T>` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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
|
||||
|
||||
14
tests/ui/regions/closure-prop-issue-104477-case1.rs
Normal file
14
tests/ui/regions/closure-prop-issue-104477-case1.rs
Normal file
|
|
@ -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>(_: T) {}
|
||||
fn test<'a, 'b>() {
|
||||
|_: &'a u8, x: MyTy<'_, 'a, 'b>| wf(x);
|
||||
|x: MyTy<'_, 'a, 'b>, _: &'a u8| wf(x);
|
||||
}
|
||||
|
||||
fn main(){}
|
||||
12
tests/ui/regions/closure-prop-issue-104477-case2.rs
Normal file
12
tests/ui/regions/closure-prop-issue-104477-case2.rs
Normal file
|
|
@ -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>(_: T) {}
|
||||
fn test<'a, 'b, 'x>() {
|
||||
|x: MyTy<'a, 'b, '_>| wf(x);
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
26
tests/ui/regions/closure-prop-issue-148289.rs
Normal file
26
tests/ui/regions/closure-prop-issue-148289.rs
Normal file
|
|
@ -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() {}
|
||||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ error: layout_of(NonZero<u32>) = 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<NonZero<u32>>) = Layout {
|
|||
offsets: [
|
||||
Size(0 bytes),
|
||||
],
|
||||
memory_index: [
|
||||
in_memory_order: [
|
||||
0,
|
||||
],
|
||||
},
|
||||
|
|
@ -248,7 +248,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
|
|||
},
|
||||
fields: Arbitrary {
|
||||
offsets: [],
|
||||
memory_index: [],
|
||||
in_memory_order: [],
|
||||
},
|
||||
largest_niche: None,
|
||||
uninhabited: false,
|
||||
|
|
@ -277,7 +277,7 @@ error: layout_of(Option<NonZero<u32>>) = 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,
|
||||
],
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue