-
-
Save davidtwco/5217cf09b356d0ee41b03a6ac929414f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs | |
index 6aeba13f639..4e1aaa0c997 100644 | |
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs | |
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs | |
@@ -85,7 +85,7 @@ fn unsize_ptr<'tcx>( | |
let mut result = None; | |
for i in 0..src_layout.fields.count() { | |
- let src_f = src_layout.field(fx, i); | |
+ let src_f = src_layout.field(fx, i).expect("tainted field ty"); | |
assert_eq!(src_layout.fields.offset(i).bytes(), 0); | |
assert_eq!(dst_layout.fields.offset(i).bytes(), 0); | |
if src_f.is_zst() { | |
@@ -93,7 +93,7 @@ fn unsize_ptr<'tcx>( | |
} | |
assert_eq!(src_layout.size, src_f.size); | |
- let dst_f = dst_layout.field(fx, i); | |
+ let dst_f = dst_layout.field(fx, i).expect("tainted field ty"); | |
assert_ne!(src_f.ty, dst_f.ty); | |
assert_eq!(result, None); | |
result = Some(unsize_ptr(fx, src, src_f, dst_f, old_info)); | |
@@ -197,7 +197,7 @@ pub(crate) fn size_and_align_of_dst<'tcx>( | |
(crate::vtable::size_of_obj(fx, info), crate::vtable::min_align_of_obj(fx, info)) | |
} | |
ty::Slice(_) | ty::Str => { | |
- let unit = layout.field(fx, 0); | |
+ let unit = layout.field(fx, 0).expect("tainted field ty"); | |
// The info in this case is the length of the str, so the size is that | |
// times the unit size. | |
( | |
@@ -218,7 +218,7 @@ pub(crate) fn size_and_align_of_dst<'tcx>( | |
// Recurse to get the size of the dynamically sized field (must be | |
// the last field). | |
- let field_layout = layout.field(fx, i); | |
+ let field_layout = layout.field(fx, i).expect("tainted field ty"); | |
let (unsized_size, mut unsized_align) = size_and_align_of_dst(fx, field_layout, info); | |
// FIXME (#26403, #27023): We should be adding padding | |
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs | |
index ec0b61a7ce5..45b31ab5da2 100644 | |
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs | |
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs | |
@@ -13,7 +13,7 @@ fn codegen_field<'tcx>( | |
field: FieldIdx, | |
) -> (Pointer, TyAndLayout<'tcx>) { | |
let field_offset = layout.fields.offset(field.index()); | |
- let field_layout = layout.field(&*fx, field.index()); | |
+ let field_layout = layout.field(&*fx, field.index()).expect("tainted field ty"); | |
let simple = |fx: &mut FunctionCx<'_, '_, '_>| { | |
(base.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()), field_layout) | |
@@ -222,7 +222,8 @@ pub(crate) fn value_field( | |
1 => val2, | |
_ => bug!("field should be 0 or 1"), | |
}; | |
- let field_layout = layout.field(&*fx, usize::from(field)); | |
+ let field_layout = | |
+ layout.field(&*fx, usize::from(field)).expect("tainted field ty"); | |
CValue::by_val(val, field_layout) | |
} | |
_ => unreachable!("value_field for ByValPair with abi {:?}", layout.abi), | |
@@ -671,7 +672,7 @@ pub(crate) fn place_field( | |
match self.inner { | |
CPlaceInner::VarPair(local, var1, var2) => { | |
- let layout = layout.field(&*fx, field.index()); | |
+ let layout = layout.field(&*fx, field.index()).expect("tainted field ty"); | |
match field.as_u32() { | |
0 => return CPlace { inner: CPlaceInner::Var(local, var1), layout }, | |
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs | |
index 43d0aafbd50..a9436770f7c 100644 | |
--- a/compiler/rustc_codegen_gcc/src/builder.rs | |
+++ b/compiler/rustc_codegen_gcc/src/builder.rs | |
@@ -862,7 +862,7 @@ fn write_operand_repeatedly(&mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, | |
self.cond_br(keep_going, body_bb, next_bb); | |
self.switch_to_block(body_bb); | |
- let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); | |
+ let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).expect("tainted field ty").size); | |
cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); | |
let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); | |
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs | |
index 521b64ad34d..af78ea0c8df 100644 | |
--- a/compiler/rustc_codegen_gcc/src/type_.rs | |
+++ b/compiler/rustc_codegen_gcc/src/type_.rs | |
@@ -250,7 +250,7 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout | |
let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); | |
for i in layout.fields.index_by_increasing_offset() { | |
let target_offset = layout.fields.offset(i as usize); | |
- let field = layout.field(cx, i); | |
+ let field = layout.field(cx, i).expect("tainted field ty"); | |
let effective_field_align = | |
layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); | |
packed |= effective_field_align < field.align.abi; | |
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs | |
index 84d57838512..14820e9cca0 100644 | |
--- a/compiler/rustc_codegen_gcc/src/type_of.rs | |
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs | |
@@ -128,7 +128,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout | |
}, | |
} | |
} | |
- FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).gcc_type(cx), count), | |
+ FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).expect("tainted field ty").gcc_type(cx), count), | |
FieldsShape::Arbitrary { .. } => | |
match name { | |
None => { | |
@@ -278,7 +278,7 @@ fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: | |
// pointee types, to avoid bitcasting every `OperandRef::deref`. | |
match self.ty.kind() { | |
ty::Ref(..) | ty::RawPtr(_) => { | |
- return self.field(cx, index).gcc_type(cx); | |
+ return self.field(cx, index).expect("tainted field ty").gcc_type(cx); | |
} | |
// only wide pointer boxes are handled as pointers | |
// thin pointer boxes with scalar allocators are handled by the general logic below | |
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | |
index c6996f2e16a..bb3466f02bc 100644 | |
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | |
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | |
@@ -230,8 +230,9 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( | |
}; | |
let layout = cx.layout_of(layout_type); | |
- let addr_field = layout.field(cx, abi::FAT_PTR_ADDR); | |
- let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA); | |
+ let addr_field = layout.field(cx, abi::FAT_PTR_ADDR).expect("tainted field ty"); | |
+ let extra_field = | |
+ layout.field(cx, abi::FAT_PTR_EXTRA).expect("tainted field ty"); | |
let (addr_field_name, extra_field_name) = match fat_pointer_kind { | |
FatPtrKind::Dyn => ("pointer", "vtable"), | |
@@ -978,7 +979,8 @@ fn build_struct_type_di_node<'ll, 'tcx>( | |
// This is struct with named fields | |
Cow::Borrowed(f.name.as_str()) | |
}; | |
- let field_layout = struct_type_and_layout.field(cx, i); | |
+ let field_layout = | |
+ struct_type_and_layout.field(cx, i).expect("tainted field ty"); | |
build_field_di_node( | |
cx, | |
owner, | |
@@ -1157,7 +1159,7 @@ fn build_union_type_di_node<'ll, 'tcx>( | |
.iter() | |
.enumerate() | |
.map(|(i, f)| { | |
- let field_layout = union_ty_and_layout.field(cx, i); | |
+ let field_layout = union_ty_and_layout.field(cx, i).expect("tainted field ty"); | |
build_field_di_node( | |
cx, | |
owner, | |
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs | |
index 88040557a9b..6ef6a8e5d41 100644 | |
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs | |
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs | |
@@ -808,7 +808,9 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( | |
})); | |
debug_assert_eq!( | |
- cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), | |
+ cx.size_and_align_of( | |
+ enum_type_and_layout.field(cx, tag_field).expect("tainted field ty").ty | |
+ ), | |
cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout)) | |
); | |
@@ -853,7 +855,9 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( | |
cx, | |
enum_type_di_node, | |
TAG_FIELD_NAME, | |
- cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), | |
+ cx.size_and_align_of( | |
+ enum_type_and_layout.field(cx, tag_field).expect("tainted field ty").ty, | |
+ ), | |
enum_type_and_layout.fields.offset(tag_field), | |
DIFlags::FlagZero, | |
tag_base_type_di_node, | |
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs | |
index b4beb80ca8b..bf3e0fa450c 100644 | |
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs | |
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs | |
@@ -281,7 +281,8 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( | |
super::tuple_field_name(field_index) | |
}; | |
- let field_layout = variant_layout.field(cx, field_index); | |
+ let field_layout = | |
+ variant_layout.field(cx, field_index).expect("tainted field ty"); | |
build_field_di_node( | |
cx, | |
@@ -362,7 +363,8 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( | |
.map(|s| Cow::from(s.as_str())) | |
.unwrap_or_else(|| super::tuple_field_name(field_index)); | |
- let field_type = variant_layout.field(cx, field_index).ty; | |
+ let field_type = | |
+ variant_layout.field(cx, field_index).expect("tainted field ty").ty; | |
build_field_di_node( | |
cx, | |
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs | |
index 2dbd467cc84..007a0c68ed5 100644 | |
--- a/compiler/rustc_codegen_llvm/src/type_of.rs | |
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs | |
@@ -80,7 +80,9 @@ fn uncached_llvm_type<'a, 'tcx>( | |
} | |
} | |
} | |
- FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count), | |
+ FieldsShape::Array { count, .. } => { | |
+ cx.type_array(layout.field(cx, 0).expect("tainted field ty").llvm_type(cx), count) | |
+ } | |
FieldsShape::Arbitrary { .. } => match name { | |
None => { | |
let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); | |
@@ -110,7 +112,7 @@ fn struct_llfields<'a, 'tcx>( | |
let mut field_remapping = smallvec![0; field_count]; | |
for i in layout.fields.index_by_increasing_offset() { | |
let target_offset = layout.fields.offset(i as usize); | |
- let field = layout.field(cx, i); | |
+ let field = layout.field(cx, i).expect("tainted field ty"); | |
let effective_field_align = | |
layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); | |
packed |= effective_field_align < field.align.abi; | |
@@ -332,7 +334,7 @@ fn scalar_pair_element_llvm_type<'a>( | |
// pointee types, to avoid bitcasting every `OperandRef::deref`. | |
match *self.ty.kind() { | |
ty::Ref(..) | ty::RawPtr(_) => { | |
- return self.field(cx, index).llvm_type(cx); | |
+ return self.field(cx, index).expect("tainted field ty").llvm_type(cx); | |
} | |
// only wide pointer boxes are handled as pointers | |
// thin pointer boxes with scalar allocators are handled by the general logic below | |
@@ -432,7 +434,7 @@ fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type | |
// Vectors, even for non-power-of-two sizes, have the same layout as | |
// arrays but don't count as aggregate types | |
if let FieldsShape::Array { count, .. } = self.layout.fields() | |
- && let element = self.field(cx, 0) | |
+ && let element = self.field(cx, 0).expect("tainted field ty") | |
&& element.ty.is_integral() | |
{ | |
// `cx.type_ix(bits)` is tempting here, but while that works great | |
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs | |
index dc862803274..310f472310c 100644 | |
--- a/compiler/rustc_codegen_ssa/src/base.rs | |
+++ b/compiler/rustc_codegen_ssa/src/base.rs | |
@@ -233,7 +233,7 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
} | |
let mut result = None; | |
for i in 0..src_layout.fields.count() { | |
- let src_f = src_layout.field(bx.cx(), i); | |
+ let src_f = src_layout.field(bx.cx(), i).expect("tainted field ty"); | |
if src_f.is_zst() { | |
continue; | |
} | |
@@ -242,7 +242,7 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
assert_eq!(dst_layout.fields.offset(i).bytes(), 0); | |
assert_eq!(src_layout.size, src_f.size); | |
- let dst_f = dst_layout.field(bx.cx(), i); | |
+ let dst_f = dst_layout.field(bx.cx(), i).expect("tainted field ty"); | |
assert_ne!(src_f.ty, dst_f.ty); | |
assert_eq!(result, None); | |
result = Some(unsize_ptr(bx, src, src_f.ty, dst_f.ty, old_info)); | |
diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs | |
index c34f1dbf856..9c13814c814 100644 | |
--- a/compiler/rustc_codegen_ssa/src/glue.rs | |
+++ b/compiler/rustc_codegen_ssa/src/glue.rs | |
@@ -38,7 +38,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
(size, align) | |
} | |
ty::Slice(_) | ty::Str => { | |
- let unit = layout.field(bx, 0); | |
+ let unit = layout.field(bx, 0).expect("tainted field ty"); | |
// The info in this case is the length of the str, so the size is that | |
// times the unit size. | |
( | |
@@ -67,7 +67,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
// Recurse to get the size of the dynamically sized field (must be | |
// the last field). | |
- let field_ty = layout.field(bx, i).ty; | |
+ let field_ty = layout.field(bx, i).expect("tainted field ty").ty; | |
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info); | |
// FIXME (#26403, #27023): We should be adding padding | |
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | |
index 34b8d8b5a6f..37028be7a96 100644 | |
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | |
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs | |
@@ -127,11 +127,11 @@ fn layout(&self) -> TyAndLayout<'tcx> { | |
} | |
fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self { | |
- self.field(bx.cx(), field.index()) | |
+ self.field(bx.cx(), field.index()).expect("tainted field ty") | |
} | |
fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self { | |
- self.field(bx.cx(), index as usize) | |
+ self.field(bx.cx(), index as usize).expect("tainted field ty") | |
} | |
fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self { | |
@@ -578,7 +578,9 @@ pub fn compute_per_local_var_debug_info( | |
mir::ProjectionElem::Field(field, _) => { | |
let i = field.index(); | |
fragment_start += fragment_layout.fields.offset(i); | |
- fragment_layout = fragment_layout.field(self.cx, i); | |
+ fragment_layout = fragment_layout | |
+ .field(self.cx, i) | |
+ .expect("tainted field ty"); | |
} | |
_ => span_bug!( | |
var.source_info.span, | |
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs | |
index 31c293d7c29..a6ea1c3c4e0 100644 | |
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs | |
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs | |
@@ -271,7 +271,7 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( | |
bx: &mut Bx, | |
i: usize, | |
) -> Self { | |
- let field = self.layout.field(bx.cx(), i); | |
+ let field = self.layout.field(bx.cx(), i).expect("tainted field ty"); | |
let offset = self.layout.fields.offset(i); | |
let mut val = match (self.val, self.layout.abi) { | |
@@ -528,7 +528,7 @@ fn maybe_codegen_consume_direct( | |
// ZSTs don't require any actual memory access. | |
// FIXME(eddyb) deduplicate this with the identical | |
// checks in `codegen_consume` and `extract_field`. | |
- let elem = o.layout.field(bx.cx(), 0); | |
+ let elem = o.layout.field(bx.cx(), 0).expect("tainted field ty"); | |
if elem.is_zst() { | |
o = OperandRef::zero_sized(elem); | |
} else { | |
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs | |
index 90eab55f76e..60c970f5fca 100644 | |
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs | |
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs | |
@@ -95,7 +95,7 @@ pub fn project_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>( | |
bx: &mut Bx, | |
ix: usize, | |
) -> Self { | |
- let field = self.layout.field(bx.cx(), ix); | |
+ let field = self.layout.field(bx.cx(), ix).expect("tainted field ty"); | |
let offset = self.layout.fields.offset(ix); | |
let effective_field_align = self.align.restrict_for_offset(offset); | |
@@ -390,7 +390,7 @@ pub fn project_index<Bx: BuilderMethods<'a, 'tcx, Value = V>>( | |
) -> Self { | |
// Statically compute the offset if we can, otherwise just use the element size, | |
// as this will yield the lowest alignment. | |
- let layout = self.layout.field(bx, 0); | |
+ let layout = self.layout.field(bx, 0).expect("tainted field ty"); | |
let offset = if let Some(llindex) = bx.const_to_opt_uint(llindex) { | |
layout.size.checked_mul(llindex, bx).unwrap_or(layout.size) | |
} else { | |
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs | |
index dd7a1fcc165..2814ca813b3 100644 | |
--- a/compiler/rustc_const_eval/src/interpret/cast.rs | |
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs | |
@@ -416,7 +416,7 @@ fn unsize_into( | |
// Example: `Arc<T>` -> `Arc<Trait>` | |
// here we need to increase the size of every &T thin ptr field to a fat ptr | |
for i in 0..src.layout.fields.count() { | |
- let cast_ty_field = cast_ty.field(self, i); | |
+ let cast_ty_field = cast_ty.field(self, i)?; | |
if cast_ty_field.is_zst() { | |
continue; | |
} | |
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs | |
index 04e046fbda3..811ae3680f5 100644 | |
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs | |
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs | |
@@ -603,7 +603,7 @@ pub(super) fn size_and_align_of( | |
// Recurse to get the size of the dynamically sized field (must be | |
// the last field). Can't have foreign types here, how would we | |
// adjust alignment and size for them? | |
- let field = layout.field(self, layout.fields.count() - 1); | |
+ let field = layout.field(self, layout.fields.count() - 1)?; | |
let Some((unsized_size, mut unsized_align)) = | |
self.size_and_align_of(metadata, &field)? | |
else { | |
@@ -651,7 +651,7 @@ pub(super) fn size_and_align_of( | |
ty::Slice(_) | ty::Str => { | |
let len = metadata.unwrap_meta().to_target_usize(self)?; | |
- let elem = layout.field(self, 0); | |
+ let elem = layout.field(self, 0)?; | |
// Make sure the slice is not too big. | |
let size = elem.size.bytes().saturating_mul(len); // we rely on `max_size_of_val` being smaller than `u64::MAX`. | |
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs | |
index d7d31fe1887..cda6a2c196e 100644 | |
--- a/compiler/rustc_const_eval/src/interpret/projection.rs | |
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs | |
@@ -40,7 +40,7 @@ pub fn mplace_field( | |
field: usize, | |
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { | |
let offset = base.layout.fields.offset(field); | |
- let field_layout = base.layout.field(self, field); | |
+ let field_layout = base.layout.field(self, field)?; | |
// Offset may need adjustment for unsized fields. | |
let (meta, offset) = if field_layout.is_unsized() { | |
@@ -96,7 +96,7 @@ pub fn operand_field( | |
Right(value) => value, | |
}; | |
- let field_layout = base.layout.field(self, field); | |
+ let field_layout = base.layout.field(self, field)?; | |
let offset = base.layout.fields.offset(field); | |
// This makes several assumptions about what layouts we will encounter; we match what | |
// codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`). | |
@@ -196,7 +196,7 @@ pub fn operand_index( | |
} | |
let offset = stride * index; // `Size` multiplication | |
// All fields have the same layout. | |
- let field_layout = base.layout.field(self, 0); | |
+ let field_layout = base.layout.field(self, 0)?; | |
base.offset(offset, field_layout, self) | |
} | |
_ => span_bug!( | |
@@ -217,7 +217,7 @@ pub fn operand_array_fields<'a>( | |
let abi::FieldsShape::Array { stride, .. } = base.layout.fields else { | |
span_bug!(self.cur_span(), "operand_array_fields: expected an array layout"); | |
}; | |
- let field_layout = base.layout.field(self, 0); | |
+ let field_layout = base.layout.field(self, 0)?; | |
let dl = &self.tcx.data_layout; | |
// `Size` multiplication | |
Ok((0..len).map(move |i| base.offset(stride * i, field_layout, dl))) | |
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs | |
index 2d1970791ca..03678455be6 100644 | |
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs | |
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs | |
@@ -136,7 +136,11 @@ fn might_permit_raw_init_lax<'tcx>( | |
} | |
FieldsShape::Arbitrary { offsets, .. } => { | |
for idx in 0..offsets.len() { | |
- if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? { | |
+ if !might_permit_raw_init_lax( | |
+ this.field(cx, idx).expect("tainted field ty"), | |
+ cx, | |
+ init_kind, | |
+ )? { | |
// We found a field that is unhappy with this kind of initialization. | |
return Ok(false); | |
} | |
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs | |
index ecbbfd92539..2d6a192f35a 100644 | |
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs | |
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs | |
@@ -139,6 +139,16 @@ fn projected_ty_from_poly_trait_ref( | |
/// report. | |
fn set_tainted_by_errors(&self, e: ErrorGuaranteed); | |
+ /// Returns the error encountered in some prior pass that was translated to | |
+ /// a ty-error (if such an error exists). | |
+ fn tainted_by_errors(&self) -> Option<ErrorGuaranteed>; | |
+ | |
+ /// Returns `true` if an error was encountered in some prior pass that was translated to | |
+ /// a ty-error. | |
+ fn is_tainted_by_errors(&self) -> bool { | |
+ self.tainted_by_errors().is_some() | |
+ } | |
+ | |
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); | |
fn astconv(&self) -> &dyn AstConv<'tcx> | |
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs | |
index c160cf2df6e..d1d8129fdde 100644 | |
--- a/compiler/rustc_hir_analysis/src/collect.rs | |
+++ b/compiler/rustc_hir_analysis/src/collect.rs | |
@@ -37,6 +37,7 @@ | |
use rustc_trait_selection::infer::InferCtxtExt; | |
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; | |
use rustc_trait_selection::traits::ObligationCtxt; | |
+use std::cell::Cell; | |
use std::iter; | |
mod generics_of; | |
@@ -113,6 +114,7 @@ pub fn provide(providers: &mut Providers) { | |
pub struct ItemCtxt<'tcx> { | |
tcx: TyCtxt<'tcx>, | |
item_def_id: LocalDefId, | |
+ tainted_by_errors: Cell<Option<ErrorGuaranteed>>, | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
@@ -337,7 +339,7 @@ fn bad_placeholder<'tcx>( | |
impl<'tcx> ItemCtxt<'tcx> { | |
pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { | |
- ItemCtxt { tcx, item_def_id } | |
+ ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } | |
} | |
pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { | |
@@ -488,8 +490,13 @@ fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> { | |
ty.ty_adt_def() | |
} | |
- fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { | |
- // There's no obvious place to track this, so just let it go. | |
+ fn set_tainted_by_errors(&self, e: ErrorGuaranteed) { | |
+ debug!("set_tainted_by_errors(ErrorGuaranteed)"); | |
+ self.tainted_by_errors.set(Some(e)); | |
+ } | |
+ | |
+ fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> { | |
+ self.tainted_by_errors.get() | |
} | |
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { | |
@@ -1174,7 +1181,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig< | |
bug!("unexpected sort of node in fn_sig(): {:?}", x); | |
} | |
}; | |
- ty::EarlyBinder::bind(output) | |
+ | |
+ if let Some(e) = icx.tainted_by_errors() { | |
+ ty::EarlyBinder::bind_tainted(output, e) | |
+ } else { | |
+ ty::EarlyBinder::bind(output) | |
+ } | |
} | |
fn infer_return_ty_for_fn_sig<'tcx>( | |
@@ -1356,18 +1368,19 @@ fn impl_trait_ref( | |
) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> { | |
let icx = ItemCtxt::new(tcx, def_id); | |
let impl_ = tcx.hir().expect_item(def_id).expect_impl(); | |
- impl_ | |
- .of_trait | |
- .as_ref() | |
- .map(|ast_trait_ref| { | |
- let selfty = tcx.type_of(def_id).instantiate_identity(); | |
- icx.astconv().instantiate_mono_trait_ref( | |
- ast_trait_ref, | |
- selfty, | |
- check_impl_constness(tcx, impl_.constness, ast_trait_ref), | |
- ) | |
- }) | |
- .map(ty::EarlyBinder::bind) | |
+ let impl_trait_ref = impl_.of_trait.as_ref().map(|ast_trait_ref| { | |
+ let selfty = tcx.type_of(def_id).instantiate_identity(); | |
+ icx.astconv().instantiate_mono_trait_ref( | |
+ ast_trait_ref, | |
+ selfty, | |
+ check_impl_constness(tcx, impl_.constness, ast_trait_ref), | |
+ ) | |
+ }); | |
+ if let Some(e) = icx.tainted_by_errors.get() { | |
+ impl_trait_ref.map(|itr| ty::EarlyBinder::bind_tainted(itr, e)) | |
+ } else { | |
+ impl_trait_ref.map(ty::EarlyBinder::bind) | |
+ } | |
} | |
fn check_impl_constness( | |
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs | |
index c39edaa1577..b406e46db3d 100644 | |
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs | |
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs | |
@@ -511,7 +511,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty | |
bug!("unexpected sort of node in type_of(): {:?}", x); | |
} | |
}; | |
- ty::EarlyBinder::bind(output) | |
+ | |
+ if let Some(e) = icx.tainted_by_errors.get() { | |
+ ty::EarlyBinder::bind_tainted(output, e) | |
+ } else { | |
+ ty::EarlyBinder::bind(output) | |
+ } | |
} | |
fn infer_placeholder_type<'a>( | |
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | |
index 6a82b00211e..c135a368a36 100644 | |
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | |
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | |
@@ -315,6 +315,10 @@ fn set_tainted_by_errors(&self, e: ErrorGuaranteed) { | |
self.infcx.set_tainted_by_errors(e) | |
} | |
+ fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> { | |
+ self.infcx.tainted_by_errors() | |
+ } | |
+ | |
fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span) { | |
// FIXME: normalization and escaping regions | |
let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty }; | |
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl | |
index bb7147ac80f..3989bd87c04 100644 | |
--- a/compiler/rustc_middle/messages.ftl | |
+++ b/compiler/rustc_middle/messages.ftl | |
@@ -1,6 +1,9 @@ | |
middle_adjust_for_foreign_abi_error = | |
target architecture {$arch} does not support `extern {$abi}` ABI | |
+middle_already_reported = | |
+ an error has already been reported elsewhere (this should not usually be printed) | |
+ | |
middle_assert_async_resume_after_panic = `async fn` resumed after panicking | |
middle_assert_async_resume_after_return = `async fn` resumed after completion | |
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs | |
index 57b2de84b47..33415c14426 100644 | |
--- a/compiler/rustc_middle/src/error.rs | |
+++ b/compiler/rustc_middle/src/error.rs | |
@@ -130,6 +130,9 @@ pub enum LayoutError<'tcx> { | |
#[diag(middle_cannot_be_normalized)] | |
NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, | |
+ #[diag(middle_already_reported)] | |
+ AlreadyReported, | |
+ | |
#[diag(middle_cycle)] | |
Cycle, | |
} | |
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs | |
index 2c481745d98..0692259cd57 100644 | |
--- a/compiler/rustc_middle/src/query/erase.rs | |
+++ b/compiler/rustc_middle/src/query/erase.rs | |
@@ -170,8 +170,25 @@ impl<T> EraseType for rustc_hir::MaybeOwner<&'_ T> { | |
type Result = [u8; size_of::<rustc_hir::MaybeOwner<&'static ()>>()]; | |
} | |
-impl<T: EraseType> EraseType for ty::EarlyBinder<T> { | |
- type Result = T::Result; | |
+impl EraseType for ty::EarlyBinder<Ty<'_>> { | |
+ type Result = [u8; size_of::<ty::EarlyBinder<Ty<'static>>>()]; | |
+} | |
+ | |
+impl EraseType for ty::EarlyBinder<ty::Const<'_>> { | |
+ type Result = [u8; size_of::<ty::EarlyBinder<ty::Const<'static>>>()]; | |
+} | |
+ | |
+impl EraseType for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> { | |
+ type Result = [u8; size_of::<ty::EarlyBinder<ty::Binder<'static, ty::FnSig<'static>>>>()]; | |
+} | |
+ | |
+impl EraseType for ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> { | |
+ type Result = [u8; size_of::<ty::EarlyBinder<&'static ty::List<ty::Clause<'static>>>>()]; | |
+} | |
+ | |
+impl EraseType for ty::EarlyBinder<&'_ [(ty::Clause<'_>, rustc_span::Span)]> { | |
+ type Result = | |
+ [u8; size_of::<ty::EarlyBinder<&'static [(ty::Clause<'static>, rustc_span::Span)]>>()]; | |
} | |
impl EraseType for ty::Binder<'_, ty::FnSig<'_>> { | |
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs | |
index 97dab5cb47e..5dd5a2c85ee 100644 | |
--- a/compiler/rustc_middle/src/ty/generic_args.rs | |
+++ b/compiler/rustc_middle/src/ty/generic_args.rs | |
@@ -11,7 +11,7 @@ | |
use rustc_hir::def_id::DefId; | |
use rustc_macros::HashStable; | |
use rustc_serialize::{self, Decodable, Encodable}; | |
-use rustc_span::sym; | |
+use rustc_span::{sym, ErrorGuaranteed}; | |
use rustc_type_ir::WithCachedTypeInfo; | |
use smallvec::SmallVec; | |
@@ -535,6 +535,9 @@ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFl | |
#[derive(Encodable, Decodable, HashStable)] | |
pub struct EarlyBinder<T> { | |
value: T, | |
+ /// If computation of `T` produced an error then this binder is "tainted", and this information | |
+ /// is useful to avoid later parts of the compilation. | |
+ tainted: Option<ErrorGuaranteed>, | |
} | |
/// For early binders, you should first call `instantiate` before using any visitors. | |
@@ -543,11 +546,15 @@ impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} | |
impl<T> EarlyBinder<T> { | |
pub fn bind(value: T) -> EarlyBinder<T> { | |
- EarlyBinder { value } | |
+ EarlyBinder { value, tainted: None } | |
+ } | |
+ | |
+ pub fn bind_tainted(value: T, tainted: ErrorGuaranteed) -> EarlyBinder<T> { | |
+ EarlyBinder { value, tainted: Some(tainted) } | |
} | |
pub fn as_ref(&self) -> EarlyBinder<&T> { | |
- EarlyBinder { value: &self.value } | |
+ EarlyBinder { value: &self.value, tainted: self.tainted } | |
} | |
pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U> | |
@@ -562,7 +569,7 @@ pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U> | |
F: FnOnce(T) -> U, | |
{ | |
let value = f(self.value); | |
- EarlyBinder { value } | |
+ EarlyBinder { value, tainted: self.tainted } | |
} | |
pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E> | |
@@ -570,11 +577,11 @@ pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E> | |
F: FnOnce(T) -> Result<U, E>, | |
{ | |
let value = f(self.value)?; | |
- Ok(EarlyBinder { value }) | |
+ Ok(EarlyBinder { value, tainted: self.tainted }) | |
} | |
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> { | |
- EarlyBinder { value } | |
+ EarlyBinder { value, tainted: self.tainted } | |
} | |
/// Skips the binder and returns the "bound" value. | |
@@ -595,14 +602,14 @@ pub fn skip_binder(self) -> T { | |
impl<T> EarlyBinder<Option<T>> { | |
pub fn transpose(self) -> Option<EarlyBinder<T>> { | |
- self.value.map(|value| EarlyBinder { value }) | |
+ self.value.map(|value| EarlyBinder { value, tainted: self.tainted }) | |
} | |
} | |
impl<T, U> EarlyBinder<(T, U)> { | |
pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) { | |
- let EarlyBinder { value: (lhs, rhs) } = self; | |
- (EarlyBinder { value: lhs }, EarlyBinder { value: rhs }) | |
+ let EarlyBinder { value: (lhs, rhs), tainted } = self; | |
+ (EarlyBinder { value: lhs, tainted }, EarlyBinder { value: rhs, tainted }) | |
} | |
} | |
@@ -638,7 +645,7 @@ impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I> | |
type Item = I::Item; | |
fn next(&mut self) -> Option<Self::Item> { | |
- Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args)) | |
+ Some(EarlyBinder::bind(self.it.next()?).instantiate(self.tcx, self.args)) | |
} | |
fn size_hint(&self) -> (usize, Option<usize>) { | |
@@ -652,7 +659,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I | |
I::Item: TypeFoldable<TyCtxt<'tcx>>, | |
{ | |
fn next_back(&mut self) -> Option<Self::Item> { | |
- Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args)) | |
+ Some(EarlyBinder::bind(self.it.next_back()?).instantiate(self.tcx, self.args)) | |
} | |
} | |
@@ -699,7 +706,7 @@ impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I> | |
type Item = <I::Item as Deref>::Target; | |
fn next(&mut self) -> Option<Self::Item> { | |
- self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) | |
+ self.it.next().map(|value| EarlyBinder::bind(*value).instantiate(self.tcx, self.args)) | |
} | |
fn size_hint(&self) -> (usize, Option<usize>) { | |
@@ -714,9 +721,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, ' | |
<I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, | |
{ | |
fn next_back(&mut self) -> Option<Self::Item> { | |
- self.it | |
- .next_back() | |
- .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) | |
+ self.it.next_back().map(|value| EarlyBinder::bind(*value).instantiate(self.tcx, self.args)) | |
} | |
} | |
@@ -742,7 +747,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> { | |
type Item = EarlyBinder<T::Item>; | |
fn next(&mut self) -> Option<Self::Item> { | |
- self.t.next().map(|value| EarlyBinder { value }) | |
+ self.t.next().map(|value| EarlyBinder::bind(value)) | |
} | |
fn size_hint(&self) -> (usize, Option<usize>) { | |
@@ -756,6 +761,14 @@ pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T { | |
self.value.fold_with(&mut folder) | |
} | |
+ pub fn instantiate_if_not_tainted( | |
+ self, | |
+ tcx: TyCtxt<'tcx>, | |
+ args: &[GenericArg<'tcx>], | |
+ ) -> Result<T, ErrorGuaranteed> { | |
+ if let Some(e) = self.tainted { Err(e) } else { Ok(self.instantiate(tcx, args)) } | |
+ } | |
+ | |
/// Makes the identity replacement `T0 => T0, ..., TN => TN`. | |
/// Conceptually, this converts universally bound variables into placeholders | |
/// when inside of a given item. | |
@@ -768,6 +781,10 @@ pub fn instantiate_identity(self) -> T { | |
self.value | |
} | |
+ pub fn instantiate_identity_if_not_tainted(self) -> Result<T, ErrorGuaranteed> { | |
+ if let Some(e) = self.tainted { Err(e) } else { Ok(self.instantiate_identity()) } | |
+ } | |
+ | |
/// Returns the inner value, but only if it contains no bound vars. | |
pub fn no_bound_vars(self) -> Option<T> { | |
if !self.value.has_param() { Some(self.value) } else { None } | |
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs | |
index 62805d1e8b5..77fd9b0719b 100644 | |
--- a/compiler/rustc_middle/src/ty/layout.rs | |
+++ b/compiler/rustc_middle/src/ty/layout.rs | |
@@ -4,7 +4,7 @@ | |
use crate::ty::normalize_erasing_regions::NormalizationError; | |
use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; | |
use rustc_error_messages::DiagnosticMessage; | |
-use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; | |
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic}; | |
use rustc_hir as hir; | |
use rustc_hir::def_id::DefId; | |
use rustc_index::IndexVec; | |
@@ -212,6 +212,7 @@ pub enum LayoutError<'tcx> { | |
Unknown(Ty<'tcx>), | |
SizeOverflow(Ty<'tcx>), | |
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), | |
+ AlreadyReported(ErrorGuaranteed), | |
Cycle, | |
} | |
@@ -223,6 +224,7 @@ pub fn diagnostic_message(&self) -> DiagnosticMessage { | |
Unknown(_) => middle_unknown_layout, | |
SizeOverflow(_) => middle_values_too_big, | |
NormalizationFailure(_, _) => middle_cannot_be_normalized, | |
+ AlreadyReported(..) => middle_already_reported, | |
Cycle => middle_cycle, | |
} | |
} | |
@@ -236,6 +238,7 @@ pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> { | |
NormalizationFailure(ty, e) => { | |
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } | |
} | |
+ AlreadyReported(..) => E::AlreadyReported, | |
Cycle => E::Cycle, | |
} | |
} | |
@@ -256,6 +259,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
t, | |
e.get_type_for_failure() | |
), | |
+ LayoutError::AlreadyReported(..) => { | |
+ write!(f, "an error has already been reported elsewhere") | |
+ } | |
LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"), | |
} | |
} | |
@@ -322,6 +328,7 @@ pub fn compute( | |
// We can't extract SizeSkeleton info from other layout errors | |
Err( | |
e @ LayoutError::Cycle | |
+ | e @ LayoutError::AlreadyReported(_) | |
| e @ LayoutError::SizeOverflow(_) | |
| e @ LayoutError::NormalizationFailure(..), | |
) => return Err(e), | |
@@ -714,6 +721,8 @@ impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx> | |
where | |
C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, | |
{ | |
+ type ErrorGuaranteed = ty::ErrorGuaranteed; | |
+ | |
fn ty_and_layout_for_variant( | |
this: TyAndLayout<'tcx>, | |
cx: &C, | |
@@ -768,7 +777,11 @@ fn ty_and_layout_for_variant( | |
TyAndLayout { ty: this.ty, layout } | |
} | |
- fn ty_and_layout_field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> TyAndLayout<'tcx> { | |
+ fn ty_and_layout_field( | |
+ this: TyAndLayout<'tcx>, | |
+ cx: &C, | |
+ i: usize, | |
+ ) -> Result<TyAndLayout<'tcx>, ty::ErrorGuaranteed> { | |
enum TyMaybeWithLayout<'tcx> { | |
Ty(Ty<'tcx>), | |
TyAndLayout(TyAndLayout<'tcx>), | |
@@ -778,7 +791,7 @@ fn field_ty_or_layout<'tcx>( | |
this: TyAndLayout<'tcx>, | |
cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), | |
i: usize, | |
- ) -> TyMaybeWithLayout<'tcx> { | |
+ ) -> Result<TyMaybeWithLayout<'tcx>, ty::ErrorGuaranteed> { | |
let tcx = cx.tcx(); | |
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> { | |
TyAndLayout { | |
@@ -822,10 +835,10 @@ fn field_ty_or_layout<'tcx>( | |
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing | |
// the `Result` should always work because the type is | |
// always either `*mut ()` or `&'static mut ()`. | |
- return TyMaybeWithLayout::TyAndLayout(TyAndLayout { | |
+ return Ok(TyMaybeWithLayout::TyAndLayout(TyAndLayout { | |
ty: this.ty, | |
..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() | |
- }); | |
+ })); | |
} | |
let mk_dyn_vtable = || { | |
@@ -879,12 +892,12 @@ fn field_ty_or_layout<'tcx>( | |
} | |
}; | |
- TyMaybeWithLayout::Ty(metadata) | |
+ Ok(TyMaybeWithLayout::Ty(metadata)) | |
} | |
// Arrays and slices. | |
- ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element), | |
- ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), | |
+ ty::Array(element, _) | ty::Slice(element) => Ok(TyMaybeWithLayout::Ty(element)), | |
+ ty::Str => Ok(TyMaybeWithLayout::Ty(tcx.types.u8)), | |
// Tuples, generators and closures. | |
ty::Closure(_, ref args) => field_ty_or_layout( | |
@@ -894,50 +907,50 @@ fn field_ty_or_layout<'tcx>( | |
), | |
ty::Generator(def_id, ref args, _) => match this.variants { | |
- Variants::Single { index } => TyMaybeWithLayout::Ty( | |
+ Variants::Single { index } => Ok(TyMaybeWithLayout::Ty( | |
args.as_generator() | |
.state_tys(def_id, tcx) | |
.nth(index.as_usize()) | |
.unwrap() | |
.nth(i) | |
.unwrap(), | |
- ), | |
+ )), | |
Variants::Multiple { tag, tag_field, .. } => { | |
if i == tag_field { | |
- return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); | |
+ return Ok(TyMaybeWithLayout::TyAndLayout(tag_layout(tag))); | |
} | |
- TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) | |
+ Ok(TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap())) | |
} | |
}, | |
- ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]), | |
+ ty::Tuple(tys) => Ok(TyMaybeWithLayout::Ty(tys[i])), | |
// ADTs. | |
ty::Adt(def, args) => { | |
match this.variants { | |
Variants::Single { index } => { | |
let field = &def.variant(index).fields[FieldIdx::from_usize(i)]; | |
- TyMaybeWithLayout::Ty(field.ty(tcx, args)) | |
+ Ok(TyMaybeWithLayout::Ty(field.ty_if_not_tainted(tcx, args)?)) | |
} | |
// Discriminant field for enums (where applicable). | |
Variants::Multiple { tag, .. } => { | |
assert_eq!(i, 0); | |
- return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); | |
+ return Ok(TyMaybeWithLayout::TyAndLayout(tag_layout(tag))); | |
} | |
} | |
} | |
ty::Dynamic(_, _, ty::DynStar) => { | |
if i == 0 { | |
- TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit)) | |
+ Ok(TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit))) | |
} else if i == 1 { | |
// FIXME(dyn-star) same FIXME as above applies here too | |
- TyMaybeWithLayout::Ty(Ty::new_imm_ref( | |
+ Ok(TyMaybeWithLayout::Ty(Ty::new_imm_ref( | |
tcx, | |
tcx.lifetimes.re_static, | |
Ty::new_array(tcx, tcx.types.usize, 3), | |
- )) | |
+ ))) | |
} else { | |
bug!("no field {i} on dyn*") | |
} | |
@@ -952,16 +965,16 @@ fn field_ty_or_layout<'tcx>( | |
} | |
} | |
- match field_ty_or_layout(this, cx, i) { | |
+ match field_ty_or_layout(this, cx, i)? { | |
TyMaybeWithLayout::Ty(field_ty) => { | |
- cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { | |
+ Ok(cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { | |
bug!( | |
"failed to get layout for `{field_ty}`: {e:?},\n\ | |
despite it being a field (#{i}) of an existing layout: {this:#?}", | |
) | |
- }) | |
+ })) | |
} | |
- TyMaybeWithLayout::TyAndLayout(field_layout) => field_layout, | |
+ TyMaybeWithLayout::TyAndLayout(field_layout) => Ok(field_layout), | |
} | |
} | |
@@ -1046,7 +1059,7 @@ fn ty_and_layout_pointee_info_at( | |
for i in 0..variant.fields.count() { | |
let field_start = variant.fields.offset(i); | |
if field_start <= offset { | |
- let field = variant.field(cx, i); | |
+ let field = variant.field(cx, i).expect("tainted field ty"); | |
result = field.to_result().ok().and_then(|field| { | |
if ptr_end <= field_start + field.size { | |
// We found the right field, look inside it. | |
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs | |
index 0411890ab51..fd86f17daed 100644 | |
--- a/compiler/rustc_middle/src/ty/mod.rs | |
+++ b/compiler/rustc_middle/src/ty/mod.rs | |
@@ -2170,6 +2170,17 @@ pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> { | |
tcx.type_of(self.did).instantiate(tcx, arg) | |
} | |
+ /// Returns the type of this field, if the type is not tainted with an error from earlier | |
+ /// in compilation. The resulting type is not normalized. The `arg` is typically obtained via | |
+ /// the second field of [`TyKind::Adt`]. | |
+ pub fn ty_if_not_tainted( | |
+ &self, | |
+ tcx: TyCtxt<'tcx>, | |
+ arg: GenericArgsRef<'tcx>, | |
+ ) -> Result<Ty<'tcx>, ErrorGuaranteed> { | |
+ tcx.type_of(self.did).instantiate_if_not_tainted(tcx, arg) | |
+ } | |
+ | |
/// Computes the `Ident` of this variant by looking up the `Span` | |
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { | |
Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) | |
diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs | |
index 247256f076b..bfb3e683fa3 100644 | |
--- a/compiler/rustc_target/src/abi/call/loongarch.rs | |
+++ b/compiler/rustc_target/src/abi/call/loongarch.rs | |
@@ -88,7 +88,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( | |
} | |
FieldsShape::Array { count, .. } => { | |
for _ in 0..count { | |
- let elem_layout = arg_layout.field(cx, 0); | |
+ let elem_layout = arg_layout.field(cx, 0).expect("tainted field ty"); | |
should_use_fp_conv_helper( | |
cx, | |
&elem_layout, | |
@@ -105,7 +105,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( | |
abi::Variants::Single { .. } => (), | |
} | |
for i in arg_layout.fields.index_by_increasing_offset() { | |
- let field = arg_layout.field(cx, i); | |
+ let field = arg_layout.field(cx, i).expect("tainted field ty"); | |
should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; | |
} | |
} | |
diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs | |
index 2700f67b209..cb4b458cc98 100644 | |
--- a/compiler/rustc_target/src/abi/call/mips64.rs | |
+++ b/compiler/rustc_target/src/abi/call/mips64.rs | |
@@ -24,7 +24,7 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg> | |
Ty: TyAbiInterface<'a, C> + Copy, | |
C: HasDataLayout, | |
{ | |
- match ret.layout.field(cx, i).abi { | |
+ match ret.layout.field(cx, i).expect("tainted field ty").abi { | |
abi::Abi::Scalar(scalar) => match scalar.primitive() { | |
abi::F32 => Some(Reg::f32()), | |
abi::F64 => Some(Reg::f64()), | |
@@ -105,7 +105,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) | |
let mut last_offset = Size::ZERO; | |
for i in 0..arg.layout.fields.count() { | |
- let field = arg.layout.field(cx, i); | |
+ let field = arg.layout.field(cx, i).expect("tainted field ty"); | |
let offset = arg.layout.fields.offset(i); | |
// We only care about aligned doubles | |
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs | |
index 03e7b3e7b40..f4a5e4f3547 100644 | |
--- a/compiler/rustc_target/src/abi/call/mod.rs | |
+++ b/compiler/rustc_target/src/abi/call/mod.rs | |
@@ -374,7 +374,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H | |
assert_eq!(start, Size::ZERO); | |
let result = if count > 0 { | |
- layout.field(cx, 0).homogeneous_aggregate(cx)? | |
+ layout.field(cx, 0).expect("tainted field ty").homogeneous_aggregate(cx)? | |
} else { | |
HomogeneousAggregate::NoData | |
}; | |
@@ -392,7 +392,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H | |
return Err(Heterogeneous); | |
} | |
- let field = layout.field(cx, i); | |
+ let field = layout.field(cx, i).expect("tainted field ty"); | |
result = result.merge(field.homogeneous_aggregate(cx)?)?; | |
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs | |
index d90dce2a087..cbd52f3c110 100644 | |
--- a/compiler/rustc_target/src/abi/call/riscv.rs | |
+++ b/compiler/rustc_target/src/abi/call/riscv.rs | |
@@ -94,7 +94,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( | |
} | |
FieldsShape::Array { count, .. } => { | |
for _ in 0..count { | |
- let elem_layout = arg_layout.field(cx, 0); | |
+ let elem_layout = arg_layout.field(cx, 0).expect("tainted field ty"); | |
should_use_fp_conv_helper( | |
cx, | |
&elem_layout, | |
@@ -111,7 +111,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( | |
abi::Variants::Single { .. } => (), | |
} | |
for i in arg_layout.fields.index_by_increasing_offset() { | |
- let field = arg_layout.field(cx, i); | |
+ let field = arg_layout.field(cx, i).expect("tainted field ty"); | |
should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; | |
} | |
} | |
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs | |
index cbed5b4afc1..bd2d7916675 100644 | |
--- a/compiler/rustc_target/src/abi/call/sparc64.rs | |
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs | |
@@ -117,7 +117,12 @@ fn parse_structure<'a, Ty, C>( | |
if offset < layout.fields.offset(i) { | |
offset = layout.fields.offset(i); | |
} | |
- data = parse_structure(cx, layout.field(cx, i), data.clone(), offset); | |
+ data = parse_structure( | |
+ cx, | |
+ layout.field(cx, i).expect("tainted_field_ty"), | |
+ data.clone(), | |
+ offset, | |
+ ); | |
} | |
} | |
_ => { | |
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs | |
index b738c3133d9..a7e07d49e79 100644 | |
--- a/compiler/rustc_target/src/abi/call/x86.rs | |
+++ b/compiler/rustc_target/src/abi/call/x86.rs | |
@@ -101,7 +101,7 @@ fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool | |
Abi::Vector { .. } => true, | |
Abi::Aggregate { .. } => { | |
for i in 0..layout.fields.count() { | |
- if contains_vector(cx, layout.field(cx, i)) { | |
+ if contains_vector(cx, layout.field(cx, i).expect("tainted field ty")) { | |
return true; | |
} | |
} | |
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs | |
index d1efe977699..17ef236b951 100644 | |
--- a/compiler/rustc_target/src/abi/call/x86_64.rs | |
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs | |
@@ -59,7 +59,7 @@ fn classify<'a, Ty, C>( | |
Abi::ScalarPair(..) | Abi::Aggregate { .. } => { | |
for i in 0..layout.fields.count() { | |
let field_off = off + layout.fields.offset(i); | |
- classify(cx, layout.field(cx, i), cls, field_off)?; | |
+ classify(cx, layout.field(cx, i).expect("tainted field ty"), cls, field_off)?; | |
} | |
match &layout.variants { | |
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs | |
index 589cd3cf96b..452a5db126e 100644 | |
--- a/compiler/rustc_target/src/abi/mod.rs | |
+++ b/compiler/rustc_target/src/abi/mod.rs | |
@@ -40,12 +40,18 @@ fn deref(&self) -> &&'a LayoutS { | |
/// Trait that needs to be implemented by the higher-level type representation | |
/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality. | |
pub trait TyAbiInterface<'a, C>: Sized { | |
+ type ErrorGuaranteed: std::fmt::Debug; | |
+ | |
fn ty_and_layout_for_variant( | |
this: TyAndLayout<'a, Self>, | |
cx: &C, | |
variant_index: VariantIdx, | |
) -> TyAndLayout<'a, Self>; | |
- fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>; | |
+ fn ty_and_layout_field( | |
+ this: TyAndLayout<'a, Self>, | |
+ cx: &C, | |
+ i: usize, | |
+ ) -> Result<TyAndLayout<'a, Self>, Self::ErrorGuaranteed>; | |
fn ty_and_layout_pointee_info_at( | |
this: TyAndLayout<'a, Self>, | |
cx: &C, | |
@@ -65,7 +71,11 @@ pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self | |
Ty::ty_and_layout_for_variant(self, cx, variant_index) | |
} | |
- pub fn field<C>(self, cx: &C, i: usize) -> Self | |
+ pub fn field<C>( | |
+ self, | |
+ cx: &C, | |
+ i: usize, | |
+ ) -> Result<Self, <Ty as TyAbiInterface<'a, C>>::ErrorGuaranteed> | |
where | |
Ty: TyAbiInterface<'a, C>, | |
{ | |
@@ -88,7 +98,7 @@ pub fn is_single_fp_element<C>(self, cx: &C) -> bool | |
Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64), | |
Abi::Aggregate { .. } => { | |
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 { | |
- self.field(cx, 0).is_single_fp_element(cx) | |
+ self.field(cx, 0).expect("tainted field ty").is_single_fp_element(cx) | |
} else { | |
false | |
} | |
@@ -134,7 +144,7 @@ pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) | |
for index in indices { | |
offset += layout.fields.offset(index); | |
- layout = layout.field(cx, index); | |
+ layout = layout.field(cx, index).expect("tainted field ty"); | |
} | |
offset | |
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs | |
index d0a7414b4ff..dd3d410b6fe 100644 | |
--- a/compiler/rustc_ty_utils/src/abi.rs | |
+++ b/compiler/rustc_ty_utils/src/abi.rs | |
@@ -584,7 +584,7 @@ fn make_thin_self_ptr<'tcx>( | |
&& !fat_pointer_layout.ty.is_ref() | |
{ | |
for i in 0..fat_pointer_layout.fields.count() { | |
- let field_layout = fat_pointer_layout.field(cx, i); | |
+ let field_layout = fat_pointer_layout.field(cx, i).expect("tainted field ty"); | |
if !field_layout.is_zst() { | |
fat_pointer_layout = field_layout; | |
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs | |
index b840ff184e0..d51d84d4c4d 100644 | |
--- a/compiler/rustc_ty_utils/src/layout.rs | |
+++ b/compiler/rustc_ty_utils/src/layout.rs | |
@@ -63,7 +63,9 @@ fn layout_of<'tcx>( | |
record_layout_for_printing(&cx, layout); | |
- sanity_check_layout(&cx, &layout); | |
+ if let Err(e) = sanity_check_layout(&cx, &layout) { | |
+ return Err(cx.tcx.arena.alloc(LayoutError::AlreadyReported(e))); | |
+ } | |
Ok(layout) | |
} | |
@@ -974,7 +976,7 @@ fn variant_info_for_adt<'tcx>( | |
.iter() | |
.enumerate() | |
.map(|(i, &name)| { | |
- let field_layout = layout.field(cx, i); | |
+ let field_layout = layout.field(cx, i).expect("tainted field ty"); | |
let offset = layout.fields.offset(i); | |
min_size = min_size.max(offset + field_layout.size); | |
FieldInfo { | |
@@ -1054,7 +1056,7 @@ fn variant_info_for_generator<'tcx>( | |
.zip(upvar_names) | |
.enumerate() | |
.map(|(field_idx, (_, name))| { | |
- let field_layout = layout.field(cx, field_idx); | |
+ let field_layout = layout.field(cx, field_idx).expect("tainted field ty"); | |
let offset = layout.fields.offset(field_idx); | |
upvars_size = upvars_size.max(offset + field_layout.size); | |
FieldInfo { | |
@@ -1077,7 +1079,8 @@ fn variant_info_for_generator<'tcx>( | |
.iter() | |
.enumerate() | |
.map(|(field_idx, local)| { | |
- let field_layout = variant_layout.field(cx, field_idx); | |
+ let field_layout = | |
+ variant_layout.field(cx, field_idx).expect("tainted field ty"); | |
let offset = variant_layout.fields.offset(field_idx); | |
// The struct is as large as the last field's end | |
variant_size = variant_size.max(offset + field_layout.size); | |
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs | |
index 8633334381a..78f081887b9 100644 | |
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs | |
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs | |
@@ -10,7 +10,7 @@ | |
pub(super) fn sanity_check_layout<'tcx>( | |
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, | |
layout: &TyAndLayout<'tcx>, | |
-) { | |
+) -> Result<(), rustc_errors::ErrorGuaranteed> { | |
// Type-level uninhabitedness should always imply ABI uninhabitedness. | |
if layout.ty.is_privately_uninhabited(cx.tcx, cx.param_env) { | |
assert!(layout.abi.is_uninhabited()); | |
@@ -22,40 +22,45 @@ pub(super) fn sanity_check_layout<'tcx>( | |
if !cfg!(debug_assertions) { | |
// Stop here, the rest is kind of expensive. | |
- return; | |
+ return Ok(()); | |
} | |
/// Yields non-ZST fields of the type | |
fn non_zst_fields<'tcx, 'a>( | |
cx: &'a LayoutCx<'tcx, TyCtxt<'tcx>>, | |
layout: &'a TyAndLayout<'tcx>, | |
- ) -> impl Iterator<Item = (Size, TyAndLayout<'tcx>)> + 'a { | |
+ ) -> impl Iterator<Item = Result<(Size, TyAndLayout<'tcx>), rustc_errors::ErrorGuaranteed>> + 'a | |
+ { | |
(0..layout.layout.fields().count()).filter_map(|i| { | |
- let field = layout.field(cx, i); | |
- // Also checking `align == 1` here leads to test failures in | |
- // `layout/zero-sized-array-union.rs`, where a type has a zero-size field with | |
- // alignment 4 that still gets ignored during layout computation (which is okay | |
- // since other fields already force alignment 4). | |
- let zst = field.is_zst(); | |
- (!zst).then(|| (layout.fields.offset(i), field)) | |
+ match layout.field(cx, i) { | |
+ Ok(field) => { | |
+ // Also checking `align == 1` here leads to test failures in | |
+ // `layout/zero-sized-array-union.rs`, where a type has a zero-size field with | |
+ // alignment 4 that still gets ignored during layout computation (which is okay | |
+ // since other fields already force alignment 4). | |
+ let zst = field.is_zst(); | |
+ (!zst).then(|| Ok((layout.fields.offset(i), field))) | |
+ } | |
+ Err(e) => Some(Err(e)), | |
+ } | |
}) | |
} | |
fn skip_newtypes<'tcx>( | |
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, | |
layout: &TyAndLayout<'tcx>, | |
- ) -> TyAndLayout<'tcx> { | |
+ ) -> Result<TyAndLayout<'tcx>, rustc_errors::ErrorGuaranteed> { | |
if matches!(layout.layout.variants(), Variants::Multiple { .. }) { | |
// Definitely not a newtype of anything. | |
- return *layout; | |
+ return Ok(*layout); | |
} | |
let mut fields = non_zst_fields(cx, layout); | |
let Some(first) = fields.next() else { | |
// No fields here, so this could be a primitive or enum -- either way it's not a newtype around a thing | |
- return *layout; | |
+ return Ok(*layout); | |
}; | |
if fields.next().is_none() { | |
- let (offset, first) = first; | |
+ let (offset, first) = first?; | |
if offset == Size::ZERO && first.layout.size() == layout.size { | |
// This is a newtype, so keep recursing. | |
// FIXME(RalfJung): I don't think it would be correct to do any checks for | |
@@ -64,10 +69,13 @@ fn skip_newtypes<'tcx>( | |
} | |
} | |
// No more newtypes here. | |
- *layout | |
+ Ok(*layout) | |
} | |
- fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayout<'tcx>) { | |
+ fn check_layout_abi<'tcx>( | |
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, | |
+ layout: &TyAndLayout<'tcx>, | |
+ ) -> Result<(), rustc_errors::ErrorGuaranteed> { | |
// Verify the ABI mandated alignment and size. | |
let align = layout.abi.inherent_align(cx).map(|align| align.abi); | |
let size = layout.abi.inherent_size(cx); | |
@@ -77,7 +85,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
Abi::Uninhabited | Abi::Aggregate { .. }, | |
"ABI unexpectedly missing alignment and/or size in {layout:#?}" | |
); | |
- return; | |
+ return Ok(()); | |
}; | |
assert_eq!( | |
layout.layout.align().abi, | |
@@ -94,7 +102,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
match layout.layout.abi() { | |
Abi::Scalar(_) => { | |
// Check that this matches the underlying field. | |
- let inner = skip_newtypes(cx, layout); | |
+ let inner = skip_newtypes(cx, layout)?; | |
assert!( | |
matches!(inner.layout.abi(), Abi::Scalar(_)), | |
"`Scalar` type {} is newtype around non-`Scalar` type {}", | |
@@ -107,7 +115,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
} | |
FieldsShape::Union(..) => { | |
// FIXME: I guess we could also check something here? Like, look at all fields? | |
- return; | |
+ return Ok(()); | |
} | |
FieldsShape::Arbitrary { .. } => { | |
// Should be an enum, the only field is the discriminant. | |
@@ -122,7 +130,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
"`Scalar` layout for multiple-field type in {inner:#?}", | |
); | |
let offset = inner.layout.fields().offset(0); | |
- let field = inner.field(cx, 0); | |
+ let field = inner.field(cx, 0).expect("tainted field ty"); | |
// The field should be at the right offset, and match the `scalar` layout. | |
assert_eq!( | |
offset, | |
@@ -146,7 +154,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
} | |
Abi::ScalarPair(scalar1, scalar2) => { | |
// Check that the underlying pair of fields matches. | |
- let inner = skip_newtypes(cx, layout); | |
+ let inner = skip_newtypes(cx, layout)?; | |
assert!( | |
matches!(inner.layout.abi(), Abi::ScalarPair(..)), | |
"`ScalarPair` type {} is newtype around non-`ScalarPair` type {}", | |
@@ -156,7 +164,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
if matches!(inner.layout.variants(), Variants::Multiple { .. }) { | |
// FIXME: ScalarPair for enums is enormously complicated and it is very hard | |
// to check anything about them. | |
- return; | |
+ return Ok(()); | |
} | |
match inner.layout.fields() { | |
FieldsShape::Arbitrary { .. } => { | |
@@ -164,7 +172,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
} | |
FieldsShape::Union(..) => { | |
// FIXME: I guess we could also check something here? Like, look at all fields? | |
- return; | |
+ return Ok(()); | |
} | |
_ => { | |
panic!("`ScalarPair` layout with unexpected field shape in {inner:#?}"); | |
@@ -175,12 +183,12 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
panic!( | |
"`ScalarPair` layout for type with not even one non-ZST field: {inner:#?}" | |
) | |
- }); | |
+ })?; | |
let (offset2, field2) = fields.next().unwrap_or_else(|| { | |
panic!( | |
"`ScalarPair` layout for type with less than two non-ZST fields: {inner:#?}" | |
) | |
- }); | |
+ })?; | |
assert_matches!( | |
fields.next(), | |
None, | |
@@ -240,9 +248,11 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
} | |
Abi::Uninhabited | Abi::Aggregate { .. } => {} // Nothing to check. | |
} | |
+ | |
+ Ok(()) | |
} | |
- check_layout_abi(cx, layout); | |
+ check_layout_abi(cx, layout)?; | |
if let Variants::Multiple { variants, .. } = &layout.variants { | |
for variant in variants.iter() { | |
@@ -296,4 +306,6 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou | |
} | |
} | |
} | |
+ | |
+ Ok(()) | |
} | |
diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs | |
index edbf4eb8f69..50ec7ae10c3 100644 | |
--- a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs | |
+++ b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.rs | |
@@ -8,11 +8,13 @@ pub struct Opcode2 { | |
impl Opcode2 { | |
pub const OP2: Opcode2 = Opcode2 { s: Opcode(0x1) }; | |
+ //~^ ERROR evaluation of constant value failed [E0080] | |
} | |
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { | |
move |i| match msg_type { | |
Opcode2::OP2 => unimplemented!(), | |
+ //~^ ERROR could not evaluate constant pattern | |
} | |
} | |
diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr | |
index 68362788545..01a5ff569c1 100644 | |
--- a/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr | |
+++ b/tests/ui/consts/issue-112824-type-mismatch-type-error-1.stderr | |
@@ -17,7 +17,19 @@ help: you might be missing a type parameter | |
LL | pub struct Opcode2<S> { | |
| +++ | |
-error: aborting due to 2 previous errors | |
+error[E0080]: evaluation of constant value failed | |
+ --> $DIR/issue-112824-type-mismatch-type-error-1.rs:10:5 | |
+ | | |
+LL | pub const OP2: Opcode2 = Opcode2 { s: Opcode(0x1) }; | |
+ | ^^^^^^^^^^^^^^^^^^^^^^ an error has already been reported elsewhere (this should not usually be printed) | |
+ | |
+error: could not evaluate constant pattern | |
+ --> $DIR/issue-112824-type-mismatch-type-error-1.rs:16:9 | |
+ | | |
+LL | Opcode2::OP2 => unimplemented!(), | |
+ | ^^^^^^^^^^^^ | |
+ | |
+error: aborting due to 4 previous errors | |
-Some errors have detailed explanations: E0261, E0412. | |
-For more information about an error, try `rustc --explain E0261`. | |
+Some errors have detailed explanations: E0080, E0261, E0412. | |
+For more information about an error, try `rustc --explain E0080`. | |
diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error.rs b/tests/ui/consts/issue-112824-type-mismatch-type-error.rs | |
index 018dfbba185..e85e3d1c6ca 100644 | |
--- a/tests/ui/consts/issue-112824-type-mismatch-type-error.rs | |
+++ b/tests/ui/consts/issue-112824-type-mismatch-type-error.rs | |
@@ -6,11 +6,13 @@ | |
impl Opcode2 { | |
pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); | |
+ //~^ ERROR evaluation of constant value failed [E0080] | |
} | |
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { | |
move |i| match msg_type { | |
Opcode2::OP2 => unimplemented!(), | |
+ //~^ ERROR could not evaluate constant pattern | |
} | |
} | |
diff --git a/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr b/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr | |
index 7ebd5ad30ac..72b7fdda0a9 100644 | |
--- a/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr | |
+++ b/tests/ui/consts/issue-112824-type-mismatch-type-error.stderr | |
@@ -17,7 +17,19 @@ help: you might be missing a type parameter | |
LL | pub struct Opcode2<S>(&'a S); | |
| +++ | |
-error: aborting due to 2 previous errors | |
+error[E0080]: evaluation of constant value failed | |
+ --> $DIR/issue-112824-type-mismatch-type-error.rs:8:5 | |
+ | | |
+LL | pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); | |
+ | ^^^^^^^^^^^^^^^^^^^^^^ an error has already been reported elsewhere (this should not usually be printed) | |
+ | |
+error: could not evaluate constant pattern | |
+ --> $DIR/issue-112824-type-mismatch-type-error.rs:14:9 | |
+ | | |
+LL | Opcode2::OP2 => unimplemented!(), | |
+ | ^^^^^^^^^^^^ | |
+ | |
+error: aborting due to 4 previous errors | |
-Some errors have detailed explanations: E0261, E0412. | |
-For more information about an error, try `rustc --explain E0261`. | |
+Some errors have detailed explanations: E0080, E0261, E0412. | |
+For more information about an error, try `rustc --explain E0080`. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment