mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Auto merge of #70672 - Dylan-DPC:rollup-cco9bbd, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #70535 (Track the finalizing node in the specialization graph) - #70590 (Miri: make backtrace function names and spans match up) - #70616 (rustc_target::abi: rename FieldPlacement to FieldsShape.) - #70626 (cargotest: remove webrender) - #70649 (clean up E0468 explanation) - #70662 (compiletest: don't use `std::io::stdout()`, as it bypasses `set_print`.) Failed merges: r? @ghost
This commit is contained in:
commit
76b11980ad
@ -79,7 +79,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
||||
};
|
||||
|
||||
match layout.fields {
|
||||
layout::FieldPlacement::Union(_) => {
|
||||
layout::FieldsShape::Union(_) => {
|
||||
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
|
||||
let packed = false;
|
||||
match name {
|
||||
@ -91,10 +91,10 @@ fn uncached_llvm_type<'a, 'tcx>(
|
||||
}
|
||||
}
|
||||
}
|
||||
layout::FieldPlacement::Array { count, .. } => {
|
||||
layout::FieldsShape::Array { count, .. } => {
|
||||
cx.type_array(layout.field(cx, 0).llvm_type(cx), count)
|
||||
}
|
||||
layout::FieldPlacement::Arbitrary { .. } => match name {
|
||||
layout::FieldsShape::Arbitrary { .. } => match name {
|
||||
None => {
|
||||
let (llfields, packed) = struct_llfields(cx, layout);
|
||||
cx.type_struct(&llfields, packed)
|
||||
@ -371,13 +371,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
match self.fields {
|
||||
layout::FieldPlacement::Union(_) => {
|
||||
layout::FieldsShape::Union(_) => {
|
||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
layout::FieldPlacement::Array { .. } => index as u64,
|
||||
layout::FieldsShape::Array { .. } => index as u64,
|
||||
|
||||
layout::FieldPlacement::Arbitrary { .. } => {
|
||||
layout::FieldsShape::Arbitrary { .. } => {
|
||||
1 + (self.fields.memory_index(index) as u64) * 2
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
}
|
||||
|
||||
pub fn len<Cx: ConstMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V {
|
||||
if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
|
||||
if let layout::FieldsShape::Array { count, .. } = self.layout.fields {
|
||||
if self.layout.is_unsized() {
|
||||
assert_eq!(count, 0);
|
||||
self.llextra.unwrap()
|
||||
|
@ -1,4 +1,4 @@
|
||||
A non-root module attempts to import macros from another crate.
|
||||
A non-root module tried to import macros from another crate.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
@ -17,7 +17,7 @@ Either move the macro import to crate root or do without the foreign macros.
|
||||
This will work:
|
||||
|
||||
```
|
||||
#[macro_use(debug_assert)]
|
||||
#[macro_use(debug_assert)] // ok!
|
||||
extern crate core;
|
||||
|
||||
mod foo {
|
||||
|
@ -53,9 +53,8 @@ pub struct ConstEvalErr<'tcx> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FrameInfo<'tcx> {
|
||||
/// This span is in the caller.
|
||||
pub call_site: Span,
|
||||
pub instance: ty::Instance<'tcx>,
|
||||
pub span: Span,
|
||||
pub lint_root: Option<hir::HirId>,
|
||||
}
|
||||
|
||||
@ -65,12 +64,12 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
|
||||
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
|
||||
== DefPathData::ClosureExpr
|
||||
{
|
||||
write!(f, "inside call to closure")?;
|
||||
write!(f, "inside closure")?;
|
||||
} else {
|
||||
write!(f, "inside call to `{}`", self.instance)?;
|
||||
write!(f, "inside `{}`", self.instance)?;
|
||||
}
|
||||
if !self.call_site.is_dummy() {
|
||||
let lo = tcx.sess.source_map().lookup_char_pos(self.call_site.lo());
|
||||
if !self.span.is_dummy() {
|
||||
let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo());
|
||||
write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?;
|
||||
}
|
||||
Ok(())
|
||||
@ -168,13 +167,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
|
||||
if let Some(span_msg) = span_msg {
|
||||
err.span_label(self.span, span_msg);
|
||||
}
|
||||
// Add spans for the stacktrace.
|
||||
// Skip the last, which is just the environment of the constant. The stacktrace
|
||||
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
|
||||
// on constant values.
|
||||
if !self.stacktrace.is_empty() {
|
||||
for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] {
|
||||
err.span_label(frame_info.call_site, frame_info.to_string());
|
||||
// Add spans for the stacktrace. Don't print a single-line backtrace though.
|
||||
if self.stacktrace.len() > 1 {
|
||||
for frame_info in &self.stacktrace {
|
||||
err.span_label(frame_info.span, frame_info.to_string());
|
||||
}
|
||||
}
|
||||
// Let the caller finish the job.
|
||||
|
@ -154,14 +154,44 @@ impl Iterator for Ancestors<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodeItem<T> {
|
||||
pub node: Node,
|
||||
pub item: T,
|
||||
/// Information about the most specialized definition of an associated item.
|
||||
pub struct LeafDef {
|
||||
/// The associated item described by this `LeafDef`.
|
||||
pub item: ty::AssocItem,
|
||||
|
||||
/// The node in the specialization graph containing the definition of `item`.
|
||||
pub defining_node: Node,
|
||||
|
||||
/// The "top-most" (ie. least specialized) specialization graph node that finalized the
|
||||
/// definition of `item`.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// trait Tr {
|
||||
/// fn assoc(&self);
|
||||
/// }
|
||||
///
|
||||
/// impl<T> Tr for T {
|
||||
/// default fn assoc(&self) {}
|
||||
/// }
|
||||
///
|
||||
/// impl Tr for u8 {}
|
||||
/// ```
|
||||
///
|
||||
/// If we start the leaf definition search at `impl Tr for u8`, that impl will be the
|
||||
/// `finalizing_node`, while `defining_node` will be the generic impl.
|
||||
///
|
||||
/// If the leaf definition search is started at the generic impl, `finalizing_node` will be
|
||||
/// `None`, since the most specialized impl we found still allows overriding the method
|
||||
/// (doesn't finalize it).
|
||||
pub finalizing_node: Option<Node>,
|
||||
}
|
||||
|
||||
impl<T> NodeItem<T> {
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
|
||||
NodeItem { node: self.node, item: f(self.item) }
|
||||
impl LeafDef {
|
||||
/// Returns whether this definition is known to not be further specializable.
|
||||
pub fn is_final(&self) -> bool {
|
||||
self.finalizing_node.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,18 +203,36 @@ impl<'tcx> Ancestors<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_item_name: Ident,
|
||||
trait_item_kind: ty::AssocKind,
|
||||
) -> Option<NodeItem<ty::AssocItem>> {
|
||||
) -> Option<LeafDef> {
|
||||
let trait_def_id = self.trait_def_id;
|
||||
let mut finalizing_node = None;
|
||||
|
||||
self.find_map(|node| {
|
||||
node.item(tcx, trait_item_name, trait_item_kind, trait_def_id)
|
||||
.map(|item| NodeItem { node, item })
|
||||
if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) {
|
||||
if finalizing_node.is_none() {
|
||||
let is_specializable = item.defaultness.is_default()
|
||||
|| tcx.impl_defaultness(node.def_id()).is_default();
|
||||
|
||||
if !is_specializable {
|
||||
finalizing_node = Some(node);
|
||||
}
|
||||
}
|
||||
|
||||
Some(LeafDef { item, defining_node: node, finalizing_node })
|
||||
} else {
|
||||
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
|
||||
finalizing_node = Some(node);
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Walk up the specialization ancestors of a given impl, starting with that
|
||||
/// impl itself. Returns `None` if an error was reported while building the
|
||||
/// specialization graph.
|
||||
/// impl itself.
|
||||
///
|
||||
/// Returns `Err` if an error was reported while building the specialization
|
||||
/// graph.
|
||||
pub fn ancestors(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
|
@ -230,7 +230,7 @@ enum StructKind {
|
||||
// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
|
||||
// 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 `FieldPlacement::Arbitrary::memory_index` for more details.
|
||||
// See also `FieldsShape::Arbitrary::memory_index` for more details.
|
||||
// FIXME(eddyb) build a better abstraction for permutations, if possible.
|
||||
fn invert_mapping(map: &[u32]) -> Vec<u32> {
|
||||
let mut inverse = vec![0; map.len()];
|
||||
@ -257,7 +257,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Arbitrary {
|
||||
fields: FieldsShape::Arbitrary {
|
||||
offsets: vec![Size::ZERO, b_offset],
|
||||
memory_index: vec![0, 1],
|
||||
},
|
||||
@ -443,7 +443,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
};
|
||||
let pair = self.scalar_pair(a.clone(), b.clone());
|
||||
let pair_offsets = match pair.fields {
|
||||
FieldPlacement::Arbitrary { ref offsets, ref memory_index } => {
|
||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||
assert_eq!(memory_index, &[0, 1]);
|
||||
offsets
|
||||
}
|
||||
@ -471,7 +471,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
Ok(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Arbitrary { offsets, memory_index },
|
||||
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||
abi,
|
||||
largest_niche,
|
||||
align,
|
||||
@ -520,7 +520,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
// The never type.
|
||||
ty::Never => tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Union(0),
|
||||
fields: FieldsShape::Union(0),
|
||||
abi: Abi::Uninhabited,
|
||||
largest_niche: None,
|
||||
align: dl.i8_align,
|
||||
@ -581,7 +581,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Array { stride: element.size, count },
|
||||
fields: FieldsShape::Array { stride: element.size, count },
|
||||
abi,
|
||||
largest_niche,
|
||||
align: element.align,
|
||||
@ -592,7 +592,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
let element = self.layout_of(element)?;
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Array { stride: element.size, count: 0 },
|
||||
fields: FieldsShape::Array { stride: element.size, count: 0 },
|
||||
abi: Abi::Aggregate { sized: false },
|
||||
largest_niche: None,
|
||||
align: element.align,
|
||||
@ -601,7 +601,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
}
|
||||
ty::Str => tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Array { stride: Size::from_bytes(1), count: 0 },
|
||||
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
|
||||
abi: Abi::Aggregate { sized: false },
|
||||
largest_niche: None,
|
||||
align: dl.i8_align,
|
||||
@ -670,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Array { stride: element.size, count },
|
||||
fields: FieldsShape::Array { stride: element.size, count },
|
||||
abi: Abi::Vector { element: scalar, count },
|
||||
largest_niche: element.largest_niche.clone(),
|
||||
size,
|
||||
@ -746,7 +746,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
return Ok(tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index },
|
||||
fields: FieldPlacement::Union(variants[index].len()),
|
||||
fields: FieldsShape::Union(variants[index].len()),
|
||||
abi,
|
||||
largest_niche: None,
|
||||
align,
|
||||
@ -980,7 +980,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
discr_index: 0,
|
||||
variants: st,
|
||||
},
|
||||
fields: FieldPlacement::Arbitrary {
|
||||
fields: FieldsShape::Arbitrary {
|
||||
offsets: vec![offset],
|
||||
memory_index: vec![0],
|
||||
},
|
||||
@ -1121,7 +1121,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
let new_ity_size = ity.size();
|
||||
for variant in &mut layout_variants {
|
||||
match variant.fields {
|
||||
FieldPlacement::Arbitrary { ref mut offsets, .. } => {
|
||||
FieldsShape::Arbitrary { ref mut offsets, .. } => {
|
||||
for i in offsets {
|
||||
if *i <= old_ity_size {
|
||||
assert_eq!(*i, old_ity_size);
|
||||
@ -1151,7 +1151,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
let mut common_prim = None;
|
||||
for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
|
||||
let offsets = match layout_variant.fields {
|
||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets,
|
||||
FieldsShape::Arbitrary { ref offsets, .. } => offsets,
|
||||
_ => bug!(),
|
||||
};
|
||||
let mut fields =
|
||||
@ -1187,7 +1187,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
if let Some((prim, offset)) = common_prim {
|
||||
let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
|
||||
let pair_offsets = match pair.fields {
|
||||
FieldPlacement::Arbitrary { ref offsets, ref memory_index } => {
|
||||
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
|
||||
assert_eq!(memory_index, &[0, 1]);
|
||||
offsets
|
||||
}
|
||||
@ -1218,7 +1218,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
discr_index: 0,
|
||||
variants: layout_variants,
|
||||
},
|
||||
fields: FieldPlacement::Arbitrary {
|
||||
fields: FieldsShape::Arbitrary {
|
||||
offsets: vec![Size::ZERO],
|
||||
memory_index: vec![0],
|
||||
},
|
||||
@ -1435,7 +1435,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
// GeneratorLayout.
|
||||
debug!("prefix = {:#?}", prefix);
|
||||
let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
|
||||
FieldPlacement::Arbitrary { mut offsets, memory_index } => {
|
||||
FieldsShape::Arbitrary { mut offsets, memory_index } => {
|
||||
let mut inverse_memory_index = invert_mapping(&memory_index);
|
||||
|
||||
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
|
||||
@ -1458,7 +1458,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
let memory_index_b = invert_mapping(&inverse_memory_index_b);
|
||||
|
||||
let outer_fields =
|
||||
FieldPlacement::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
|
||||
FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
|
||||
(outer_fields, offsets_b, memory_index_b)
|
||||
}
|
||||
_ => bug!(),
|
||||
@ -1492,7 +1492,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
variant.variants = Variants::Single { index };
|
||||
|
||||
let (offsets, memory_index) = match variant.fields {
|
||||
FieldPlacement::Arbitrary { offsets, memory_index } => (offsets, memory_index),
|
||||
FieldsShape::Arbitrary { offsets, memory_index } => (offsets, memory_index),
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
@ -1535,7 +1535,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
|
||||
let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
|
||||
|
||||
variant.fields = FieldPlacement::Arbitrary {
|
||||
variant.fields = FieldsShape::Arbitrary {
|
||||
offsets: combined_offsets,
|
||||
memory_index: combined_memory_index,
|
||||
};
|
||||
@ -1990,7 +1990,7 @@ where
|
||||
if index == variant_index &&
|
||||
// Don't confuse variants of uninhabited enums with the enum itself.
|
||||
// For more details see https://github.com/rust-lang/rust/issues/69763.
|
||||
this.fields != FieldPlacement::Union(0) =>
|
||||
this.fields != FieldsShape::Union(0) =>
|
||||
{
|
||||
this.layout
|
||||
}
|
||||
@ -2008,7 +2008,7 @@ where
|
||||
let tcx = cx.tcx();
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: variant_index },
|
||||
fields: FieldPlacement::Union(fields),
|
||||
fields: FieldsShape::Union(fields),
|
||||
abi: Abi::Uninhabited,
|
||||
largest_niche: None,
|
||||
align: tcx.data_layout.i8_align,
|
||||
@ -2054,7 +2054,7 @@ where
|
||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||
// This provides information about, e.g., DST struct pointees
|
||||
// (which may have no non-DST form), and will work as long
|
||||
// as the `Abi` or `FieldPlacement` is checked by users.
|
||||
// as the `Abi` or `FieldsShape` is checked by users.
|
||||
if i == 0 {
|
||||
let nil = tcx.mk_unit();
|
||||
let ptr_ty = if this.ty.is_unsafe_ptr() {
|
||||
@ -2219,7 +2219,7 @@ where
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
// We're not interested in any unions.
|
||||
if let FieldPlacement::Union(_) = variant.fields {
|
||||
if let FieldsShape::Union(_) = variant.fields {
|
||||
data_variant = None;
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ pub fn error_to_const_error<'mir, 'tcx, M: Machine<'mir, 'tcx>>(
|
||||
mut error: InterpErrorInfo<'tcx>,
|
||||
) -> ConstEvalErr<'tcx> {
|
||||
error.print_backtrace();
|
||||
let stacktrace = ecx.generate_stacktrace(None);
|
||||
let stacktrace = ecx.generate_stacktrace();
|
||||
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||
|
||||
ecx.push_stack_frame(
|
||||
cid.instance,
|
||||
body.span,
|
||||
body,
|
||||
Some(ret.into()),
|
||||
StackPopCleanup::None { cleanup: false },
|
||||
|
@ -8,9 +8,9 @@ use std::hash::Hash;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
use rustc_ast::ast::Mutability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::AssertMessage;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{def_id::DefId, Span};
|
||||
|
||||
use crate::interpret::{
|
||||
self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
|
||||
@ -64,7 +64,6 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> {
|
||||
/// If this returns successfully (`Ok`), the function should just be evaluated normally.
|
||||
fn hook_panic_fn(
|
||||
&mut self,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -77,7 +76,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> {
|
||||
|
||||
let msg_place = self.deref_operand(args[0])?;
|
||||
let msg = Symbol::intern(self.read_str(msg_place)?);
|
||||
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
|
||||
let span = self.find_closest_untracked_caller_location();
|
||||
let (file, line, col) = self.location_triple_for_span(span);
|
||||
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
|
||||
} else {
|
||||
@ -191,7 +190,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
||||
@ -213,7 +211,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||
} else {
|
||||
// Some functions we support even if they are non-const -- but avoid testing
|
||||
// that for const fn!
|
||||
ecx.hook_panic_fn(span, instance, args)?;
|
||||
ecx.hook_panic_fn(instance, args)?;
|
||||
// We certainly do *not* want to actually call the fn
|
||||
// though, so be sure we return here.
|
||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||
@ -248,13 +246,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
||||
_unwind: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if ecx.emulate_intrinsic(span, instance, args, ret)? {
|
||||
if ecx.emulate_intrinsic(instance, args, ret)? {
|
||||
return Ok(());
|
||||
}
|
||||
// An intrinsic that we do not support
|
||||
|
@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{self, Align, HasDataLayout, LayoutOf, Size, TyAnd
|
||||
use rustc_middle::ty::query::TyCtxtAt;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::source_map::{self, Span, DUMMY_SP};
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
|
||||
use super::{
|
||||
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
|
||||
@ -57,9 +57,6 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
|
||||
/// The def_id and substs of the current function.
|
||||
pub instance: ty::Instance<'tcx>,
|
||||
|
||||
/// The span of the call site.
|
||||
pub span: source_map::Span,
|
||||
|
||||
/// Extra data for the machine.
|
||||
pub extra: Extra,
|
||||
|
||||
@ -502,7 +499,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
pub fn push_stack_frame(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
span: Span,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
|
||||
return_to_block: StackPopCleanup,
|
||||
@ -522,7 +518,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// empty local array, we fill it in below, after we are inside the stack frame and
|
||||
// all methods actually know about the frame
|
||||
locals: IndexVec::new(),
|
||||
span,
|
||||
instance,
|
||||
stmt: 0,
|
||||
extra,
|
||||
@ -541,7 +536,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// statics and constants don't have `Storage*` statements, no need to look for them
|
||||
Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {}
|
||||
_ => {
|
||||
trace!("push_stack_frame: {:?}: num_bbs: {}", span, body.basic_blocks().len());
|
||||
for block in body.basic_blocks() {
|
||||
for stmt in block.statements.iter() {
|
||||
use rustc_middle::mir::StatementKind::{StorageDead, StorageLive};
|
||||
@ -859,33 +853,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
|
||||
let mut last_span = None;
|
||||
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
|
||||
let mut frames = Vec::new();
|
||||
for frame in self.stack().iter().rev() {
|
||||
// make sure we don't emit frames that are duplicates of the previous
|
||||
if explicit_span == Some(frame.span) {
|
||||
last_span = Some(frame.span);
|
||||
continue;
|
||||
}
|
||||
if let Some(last) = last_span {
|
||||
if last == frame.span {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
last_span = Some(frame.span);
|
||||
}
|
||||
|
||||
let lint_root = frame.current_source_info().and_then(|source_info| {
|
||||
let source_info = frame.current_source_info();
|
||||
let lint_root = source_info.and_then(|source_info| {
|
||||
match &frame.body.source_scopes[source_info.scope].local_data {
|
||||
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
|
||||
mir::ClearCrossCrate::Clear => None,
|
||||
}
|
||||
});
|
||||
let span = source_info.map_or(DUMMY_SP, |source_info| source_info.span);
|
||||
|
||||
frames.push(FrameInfo { call_site: frame.span, instance: frame.instance, lint_root });
|
||||
frames.push(FrameInfo { span, instance: frame.instance, lint_root });
|
||||
}
|
||||
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
|
||||
trace!("generate stacktrace: {:#?}", frames);
|
||||
frames
|
||||
}
|
||||
}
|
||||
@ -899,7 +881,6 @@ where
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
|
||||
self.body.hash_stable(hcx, hasher);
|
||||
self.instance.hash_stable(hcx, hasher);
|
||||
self.span.hash_stable(hcx, hasher);
|
||||
self.return_to_block.hash_stable(hcx, hasher);
|
||||
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
|
||||
self.locals.hash_stable(hcx, hasher);
|
||||
|
@ -15,7 +15,6 @@ use rustc_middle::ty::layout::{LayoutOf, Primitive, Size};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::{ImmTy, InterpCx, Machine, OpTy, PlaceTy};
|
||||
|
||||
@ -78,7 +77,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
/// Returns `true` if emulation happened.
|
||||
pub fn emulate_intrinsic(
|
||||
&mut self,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, M::PointerTag>],
|
||||
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
|
||||
@ -101,7 +99,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// `src/librustc_middle/ty/constness.rs`
|
||||
match intrinsic_name {
|
||||
sym::caller_location => {
|
||||
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
|
||||
let span = self.find_closest_untracked_caller_location();
|
||||
let location = self.alloc_caller_location_for_span(span);
|
||||
self.write_scalar(location.ptr, dest)?;
|
||||
}
|
||||
@ -118,7 +116,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
sym::needs_drop => self.tcx.types.bool,
|
||||
sym::type_id => self.tcx.types.u64,
|
||||
sym::type_name => self.tcx.mk_static_str(),
|
||||
_ => span_bug!(span, "Already checked for nullary intrinsics"),
|
||||
_ => bug!("already checked for nullary intrinsics"),
|
||||
};
|
||||
let val = self.const_eval(gid, ty)?;
|
||||
self.copy_op(val, dest)?;
|
||||
|
@ -12,18 +12,21 @@ use crate::interpret::{
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
|
||||
/// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
|
||||
/// `None` is returned and the callsite of the function invocation itself should be used.
|
||||
crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
|
||||
let mut caller_span = None;
|
||||
for next_caller in self.stack.iter().rev() {
|
||||
if !next_caller.instance.def.requires_caller_location(*self.tcx) {
|
||||
return caller_span;
|
||||
}
|
||||
caller_span = Some(next_caller.span);
|
||||
}
|
||||
|
||||
caller_span
|
||||
/// frame which is not `#[track_caller]`.
|
||||
crate fn find_closest_untracked_caller_location(&self) -> Span {
|
||||
self.stack
|
||||
.iter()
|
||||
.rev()
|
||||
// Find first non-`#[track_caller]` frame.
|
||||
.find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
|
||||
// Assert that there is always such a frame.
|
||||
.unwrap()
|
||||
.current_source_info()
|
||||
// Assert that the frame we look at is actually executing code currently
|
||||
// (`current_source_info` is None when we are unwinding and the frame does
|
||||
// not require cleanup).
|
||||
.unwrap()
|
||||
.span
|
||||
}
|
||||
|
||||
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
|
||||
|
@ -7,7 +7,7 @@ use std::hash::Hash;
|
||||
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{def_id::DefId, Span};
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use super::{
|
||||
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
|
||||
@ -135,7 +135,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
/// was used.
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
|
||||
@ -156,7 +155,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
/// responsibility to advance the instruction pointer as appropriate.
|
||||
fn call_intrinsic(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
span: Span,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
|
||||
|
@ -219,7 +219,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
|
||||
// Go through the layout. There are lots of types that support a length,
|
||||
// e.g., SIMD types.
|
||||
match self.layout.fields {
|
||||
layout::FieldPlacement::Array { count, .. } => Ok(count),
|
||||
layout::FieldsShape::Array { count, .. } => Ok(count),
|
||||
_ => bug!("len not supported on sized type {:?}", self.layout.ty),
|
||||
}
|
||||
}
|
||||
@ -437,7 +437,7 @@ where
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||
// Not using the layout method because we want to compute on u64
|
||||
match base.layout.fields {
|
||||
layout::FieldPlacement::Array { stride, .. } => {
|
||||
layout::FieldsShape::Array { stride, .. } => {
|
||||
let len = base.len(self)?;
|
||||
if index >= len {
|
||||
// This can only be reached in ConstProp and non-rustc-MIR.
|
||||
@ -463,7 +463,7 @@ where
|
||||
{
|
||||
let len = base.len(self)?; // also asserts that we have a type where this makes sense
|
||||
let stride = match base.layout.fields {
|
||||
layout::FieldPlacement::Array { stride, .. } => stride,
|
||||
layout::FieldsShape::Array { stride, .. } => stride,
|
||||
_ => bug!("mplace_array_fields: expected an array layout"),
|
||||
};
|
||||
let layout = base.layout.field(self, 0)?;
|
||||
@ -493,7 +493,7 @@ where
|
||||
// Not using layout method because that works with usize, and does not work with slices
|
||||
// (that have count 0 in their layout).
|
||||
let from_offset = match base.layout.fields {
|
||||
layout::FieldPlacement::Array { stride, .. } => stride * from, // `Size` multiplication is checked
|
||||
layout::FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
|
||||
_ => bug!("Unexpected layout of index access: {:#?}", base.layout),
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,6 @@ use std::convert::TryFrom;
|
||||
use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{
|
||||
@ -71,14 +70,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Some((dest, ret)) => Some((self.eval_place(dest)?, ret)),
|
||||
None => None,
|
||||
};
|
||||
self.eval_fn_call(
|
||||
fn_val,
|
||||
terminator.source_info.span,
|
||||
abi,
|
||||
&args[..],
|
||||
ret,
|
||||
*cleanup,
|
||||
)?;
|
||||
self.eval_fn_call(fn_val, abi, &args[..], ret, *cleanup)?;
|
||||
}
|
||||
|
||||
Drop { location, target, unwind } => {
|
||||
@ -88,7 +80,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
|
||||
|
||||
let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
|
||||
self.drop_in_place(place, instance, terminator.source_info.span, target, unwind)?;
|
||||
self.drop_in_place(place, instance, target, unwind)?;
|
||||
}
|
||||
|
||||
Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||
@ -196,7 +188,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
fn eval_fn_call(
|
||||
&mut self,
|
||||
fn_val: FnVal<'tcx, M::ExtraFnVal>,
|
||||
span: Span,
|
||||
caller_abi: Abi,
|
||||
args: &[OpTy<'tcx, M::PointerTag>],
|
||||
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
|
||||
@ -242,7 +233,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
match instance.def {
|
||||
ty::InstanceDef::Intrinsic(..) => {
|
||||
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
|
||||
M::call_intrinsic(self, span, instance, args, ret, unwind)
|
||||
M::call_intrinsic(self, instance, args, ret, unwind)
|
||||
}
|
||||
ty::InstanceDef::VtableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
@ -252,14 +243,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::Item(_) => {
|
||||
// We need MIR for this fn
|
||||
let body = match M::find_mir_or_eval_fn(self, span, instance, args, ret, unwind)? {
|
||||
let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
|
||||
Some(body) => body,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
self.push_stack_frame(
|
||||
instance,
|
||||
span,
|
||||
body,
|
||||
ret.map(|p| p.0),
|
||||
StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
|
||||
@ -407,7 +397,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
OpTy::from(ImmTy { layout: this_receiver_ptr, imm: receiver_place.ptr.into() });
|
||||
trace!("Patched self operand to {:#?}", args[0]);
|
||||
// recurse with concrete function
|
||||
self.eval_fn_call(drop_fn, span, caller_abi, &args, ret, unwind)
|
||||
self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,7 +406,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
&mut self,
|
||||
place: PlaceTy<'tcx, M::PointerTag>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
span: Span,
|
||||
target: mir::BasicBlock,
|
||||
unwind: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -444,7 +433,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
self.eval_fn_call(
|
||||
FnVal::Instance(instance),
|
||||
span,
|
||||
Abi::Rust,
|
||||
&[arg.into()],
|
||||
Some((dest.into(), target)),
|
||||
|
@ -207,10 +207,10 @@ macro_rules! make_value_visitor {
|
||||
|
||||
// Visit the fields of this value.
|
||||
match v.layout().fields {
|
||||
layout::FieldPlacement::Union(fields) => {
|
||||
layout::FieldsShape::Union(fields) => {
|
||||
self.visit_union(v, fields)?;
|
||||
},
|
||||
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
|
||||
layout::FieldsShape::Arbitrary { ref offsets, .. } => {
|
||||
// FIXME: We collect in a vec because otherwise there are lifetime
|
||||
// errors: Projecting to a field needs access to `ecx`.
|
||||
let fields: Vec<InterpResult<'tcx, Self::V>> =
|
||||
@ -220,7 +220,7 @@ macro_rules! make_value_visitor {
|
||||
.collect();
|
||||
self.visit_aggregate(v, fields.into_iter())?;
|
||||
},
|
||||
layout::FieldPlacement::Array { .. } => {
|
||||
layout::FieldsShape::Array { .. } => {
|
||||
// Let's get an mplace first.
|
||||
let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
|
||||
// Now we can go over all the fields.
|
||||
|
@ -183,7 +183,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_span: Span,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
||||
@ -204,7 +203,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||
|
||||
fn call_intrinsic(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_span: Span,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
_args: &[OpTy<'tcx>],
|
||||
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
||||
@ -361,7 +359,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
|
||||
ecx.push_stack_frame(
|
||||
Instance::new(def_id, substs),
|
||||
span,
|
||||
dummy_body,
|
||||
ret.map(Into::into),
|
||||
StackPopCleanup::None { cleanup: false },
|
||||
|
@ -49,7 +49,7 @@ where
|
||||
// use of float registers to structures (not unions) containing exactly one or two
|
||||
// float fields.
|
||||
|
||||
if let abi::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
|
||||
if let abi::FieldsShape::Arbitrary { .. } = ret.layout.fields {
|
||||
if ret.layout.fields.count() == 1 {
|
||||
if let Some(reg) = float_reg(cx, ret, 0) {
|
||||
ret.cast_to(reg);
|
||||
@ -88,15 +88,15 @@ where
|
||||
let mut prefix_index = 0;
|
||||
|
||||
match arg.layout.fields {
|
||||
abi::FieldPlacement::Array { .. } => {
|
||||
abi::FieldsShape::Array { .. } => {
|
||||
// Arrays are passed indirectly
|
||||
arg.make_indirect();
|
||||
return;
|
||||
}
|
||||
abi::FieldPlacement::Union(_) => {
|
||||
abi::FieldsShape::Union(_) => {
|
||||
// Unions and are always treated as a series of 64-bit integer chunks
|
||||
}
|
||||
abi::FieldPlacement::Arbitrary { .. } => {
|
||||
abi::FieldsShape::Arbitrary { .. } => {
|
||||
// Structures are split up into a series of 64-bit integer chunks, but any aligned
|
||||
// doubles not part of another aggregate are passed as floats.
|
||||
let mut last_offset = Size::ZERO;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::abi::{self, Abi, Align, FieldPlacement, Size};
|
||||
use crate::abi::{self, Abi, Align, FieldsShape, Size};
|
||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
||||
use crate::spec::{self, HasTargetSpec};
|
||||
|
||||
@ -315,7 +315,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
start: Size|
|
||||
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
||||
let is_union = match layout.fields {
|
||||
FieldPlacement::Array { count, .. } => {
|
||||
FieldsShape::Array { count, .. } => {
|
||||
assert_eq!(start, Size::ZERO);
|
||||
|
||||
let result = if count > 0 {
|
||||
@ -325,8 +325,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
};
|
||||
return Ok((result, layout.size));
|
||||
}
|
||||
FieldPlacement::Union(_) => true,
|
||||
FieldPlacement::Arbitrary { .. } => false,
|
||||
FieldsShape::Union(_) => true,
|
||||
FieldsShape::Arbitrary { .. } => false,
|
||||
};
|
||||
|
||||
let mut result = HomogeneousAggregate::NoData;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
||||
use crate::abi::{
|
||||
self, Abi, FieldPlacement, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
|
||||
self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
|
||||
};
|
||||
use crate::spec::HasTargetSpec;
|
||||
|
||||
@ -87,12 +87,12 @@ where
|
||||
},
|
||||
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
|
||||
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
|
||||
FieldPlacement::Union(_) => {
|
||||
FieldsShape::Union(_) => {
|
||||
if !arg_layout.is_zst() {
|
||||
return Err(CannotUseFpConv);
|
||||
}
|
||||
}
|
||||
FieldPlacement::Array { count, .. } => {
|
||||
FieldsShape::Array { count, .. } => {
|
||||
for _ in 0..count {
|
||||
let elem_layout = arg_layout.field(cx, 0);
|
||||
should_use_fp_conv_helper(
|
||||
@ -105,7 +105,7 @@ where
|
||||
)?;
|
||||
}
|
||||
}
|
||||
FieldPlacement::Arbitrary { .. } => {
|
||||
FieldsShape::Arbitrary { .. } => {
|
||||
match arg_layout.variants {
|
||||
abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
|
||||
abi::Variants::Single { .. } => (),
|
||||
|
@ -618,7 +618,7 @@ impl Scalar {
|
||||
|
||||
/// Describes how the fields of a type are located in memory.
|
||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum FieldPlacement {
|
||||
pub enum FieldsShape {
|
||||
/// All fields start at no offset. The `usize` is the field count.
|
||||
///
|
||||
/// In the case of primitives the number of fields is `0`.
|
||||
@ -657,38 +657,38 @@ pub enum FieldPlacement {
|
||||
},
|
||||
}
|
||||
|
||||
impl FieldPlacement {
|
||||
impl FieldsShape {
|
||||
pub fn count(&self) -> usize {
|
||||
match *self {
|
||||
FieldPlacement::Union(count) => count,
|
||||
FieldPlacement::Array { count, .. } => {
|
||||
FieldsShape::Union(count) => count,
|
||||
FieldsShape::Array { count, .. } => {
|
||||
let usize_count = count as usize;
|
||||
assert_eq!(usize_count as u64, count);
|
||||
usize_count
|
||||
}
|
||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len(),
|
||||
FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, i: usize) -> Size {
|
||||
match *self {
|
||||
FieldPlacement::Union(count) => {
|
||||
FieldsShape::Union(count) => {
|
||||
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
|
||||
Size::ZERO
|
||||
}
|
||||
FieldPlacement::Array { stride, count } => {
|
||||
FieldsShape::Array { stride, count } => {
|
||||
let i = u64::try_from(i).unwrap();
|
||||
assert!(i < count);
|
||||
stride * i
|
||||
}
|
||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i],
|
||||
FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn memory_index(&self, i: usize) -> usize {
|
||||
match *self {
|
||||
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
|
||||
FieldPlacement::Arbitrary { ref memory_index, .. } => {
|
||||
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||
FieldsShape::Arbitrary { ref memory_index, .. } => {
|
||||
let r = memory_index[i];
|
||||
assert_eq!(r as usize as u32, r);
|
||||
r as usize
|
||||
@ -704,7 +704,7 @@ impl FieldPlacement {
|
||||
let use_small = self.count() <= inverse_small.len();
|
||||
|
||||
// We have to write this logic twice in order to keep the array small.
|
||||
if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
|
||||
if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
|
||||
if use_small {
|
||||
for i in 0..self.count() {
|
||||
inverse_small[memory_index[i] as usize] = i as u8;
|
||||
@ -718,8 +718,8 @@ impl FieldPlacement {
|
||||
}
|
||||
|
||||
(0..self.count()).map(move |i| match *self {
|
||||
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
|
||||
FieldPlacement::Arbitrary { .. } => {
|
||||
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||
FieldsShape::Arbitrary { .. } => {
|
||||
if use_small {
|
||||
inverse_small[i] as usize
|
||||
} else {
|
||||
@ -888,7 +888,7 @@ impl Niche {
|
||||
pub struct Layout {
|
||||
/// Says where the fields are located within the layout.
|
||||
/// Primitives and uninhabited enums appear as unions without fields.
|
||||
pub fields: FieldPlacement,
|
||||
pub fields: FieldsShape,
|
||||
|
||||
/// Encodes information about multi-variant layouts.
|
||||
/// Even with `Multiple` variants, a layout still has its own fields! Those are then
|
||||
@ -923,7 +923,7 @@ impl Layout {
|
||||
let align = scalar.value.align(cx);
|
||||
Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldPlacement::Union(0),
|
||||
fields: FieldsShape::Union(0),
|
||||
abi: Abi::Scalar(scalar),
|
||||
largest_niche,
|
||||
size,
|
||||
|
@ -54,7 +54,6 @@ pub use self::project::{
|
||||
};
|
||||
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
|
||||
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
|
||||
pub use self::specialize::find_associated_item;
|
||||
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
|
||||
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
||||
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
|
||||
@ -64,8 +63,7 @@ pub use self::structural_match::NonStructuralMatchTy;
|
||||
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
|
||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||
pub use self::util::{
|
||||
get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
|
||||
predicate_for_trait_def, upcast_choices,
|
||||
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
|
||||
};
|
||||
pub use self::util::{
|
||||
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
|
||||
|
@ -1015,49 +1015,21 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
|
||||
.map_err(|ErrorReported| ())?;
|
||||
|
||||
let is_default = if node_item.node.is_from_trait() {
|
||||
// If true, the impl inherited a `type Foo = Bar`
|
||||
// given in the trait, which is implicitly default.
|
||||
// Otherwise, the impl did not specify `type` and
|
||||
// neither did the trait:
|
||||
//
|
||||
// ```rust
|
||||
// trait Foo { type T; }
|
||||
// impl Foo for Bar { }
|
||||
// ```
|
||||
//
|
||||
// This is an error, but it will be
|
||||
// reported in `check_impl_items_against_trait`.
|
||||
// We accept it here but will flag it as
|
||||
// an error when we confirm the candidate
|
||||
// (which will ultimately lead to `normalize_to_error`
|
||||
// being invoked).
|
||||
false
|
||||
if node_item.is_final() {
|
||||
// Non-specializable items are always projectable.
|
||||
true
|
||||
} else {
|
||||
// If we're looking at a trait *impl*, the item is
|
||||
// specializable if the impl or the item are marked
|
||||
// `default`.
|
||||
node_item.item.defaultness.is_default()
|
||||
|| super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
|
||||
};
|
||||
|
||||
match is_default {
|
||||
// Non-specializable items are always projectable
|
||||
false => true,
|
||||
|
||||
// Only reveal a specializable default if we're past type-checking
|
||||
// and the obligation is monomorphic, otherwise passes such as
|
||||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
true if obligation.param_env.reveal == Reveal::All => {
|
||||
if obligation.param_env.reveal == Reveal::All {
|
||||
// NOTE(eddyb) inference variables can resolve to parameters, so
|
||||
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
||||
let poly_trait_ref =
|
||||
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
|
||||
!poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
|
||||
}
|
||||
|
||||
true => {
|
||||
} else {
|
||||
debug!(
|
||||
"assemble_candidates_from_impls: not eligible due to default: \
|
||||
assoc_ty={} predicate={}",
|
||||
@ -1422,7 +1394,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||
return Progress { ty: tcx.types.err, obligations: nested };
|
||||
}
|
||||
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
|
||||
let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
|
||||
let substs =
|
||||
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
|
||||
let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
|
||||
let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
||||
tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
|
||||
@ -1447,7 +1420,7 @@ fn assoc_ty_def(
|
||||
selcx: &SelectionContext<'_, '_>,
|
||||
impl_def_id: DefId,
|
||||
assoc_ty_def_id: DefId,
|
||||
) -> Result<specialization_graph::NodeItem<ty::AssocItem>, ErrorReported> {
|
||||
) -> Result<specialization_graph::LeafDef, ErrorReported> {
|
||||
let tcx = selcx.tcx();
|
||||
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
|
||||
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
|
||||
@ -1464,9 +1437,10 @@ fn assoc_ty_def(
|
||||
if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
|
||||
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
|
||||
{
|
||||
return Ok(specialization_graph::NodeItem {
|
||||
node: specialization_graph::Node::Impl(impl_def_id),
|
||||
return Ok(specialization_graph::LeafDef {
|
||||
item: *item,
|
||||
defining_node: impl_node,
|
||||
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use rustc_errors::struct_span_err;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
|
||||
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
||||
use rustc_span::DUMMY_SP;
|
||||
@ -112,48 +112,6 @@ pub fn translate_substs<'a, 'tcx>(
|
||||
source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
|
||||
}
|
||||
|
||||
/// Given a selected impl described by `impl_data`, returns the
|
||||
/// definition and substitutions for the method with the name `name`
|
||||
/// the kind `kind`, and trait method substitutions `substs`, in
|
||||
/// that impl, a less specialized impl, or the trait default,
|
||||
/// whichever applies.
|
||||
pub fn find_associated_item<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
item: &ty::AssocItem,
|
||||
substs: SubstsRef<'tcx>,
|
||||
impl_data: &super::VtableImplData<'tcx, ()>,
|
||||
) -> (DefId, SubstsRef<'tcx>) {
|
||||
debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
|
||||
assert!(!substs.needs_infer());
|
||||
|
||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
|
||||
if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) {
|
||||
match ancestors.leaf_def(tcx, item.ident, item.kind) {
|
||||
Some(node_item) => {
|
||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = param_env.with_reveal_all();
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(
|
||||
&infcx,
|
||||
param_env,
|
||||
impl_data.impl_def_id,
|
||||
substs,
|
||||
node_item.node,
|
||||
);
|
||||
infcx.tcx.erase_regions(&substs)
|
||||
});
|
||||
(node_item.item.def_id, substs)
|
||||
}
|
||||
None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
|
||||
}
|
||||
} else {
|
||||
(item.def_id, substs)
|
||||
}
|
||||
}
|
||||
|
||||
/// Is `impl1` a specialization of `impl2`?
|
||||
///
|
||||
/// Specialization is determined by the sets of types to which the impls apply;
|
||||
|
@ -4,7 +4,6 @@ use smallvec::smallvec;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::outlives::Component;
|
||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
||||
@ -651,22 +650,8 @@ pub fn generator_trait_ref_and_outputs(
|
||||
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
|
||||
}
|
||||
|
||||
pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
|
||||
match tcx.hir().as_local_hir_id(node_item_def_id) {
|
||||
Some(hir_id) => {
|
||||
let item = tcx.hir().expect_item(hir_id);
|
||||
if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
|
||||
defaultness.is_default()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
None => tcx.impl_defaultness(node_item_def_id).is_default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
|
||||
assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
|
||||
assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final()
|
||||
}
|
||||
|
||||
pub enum TupleArgumentsFlag {
|
||||
|
@ -1,9 +1,11 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
|
||||
use rustc_span::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use traits::{translate_substs, Reveal};
|
||||
|
||||
use log::debug;
|
||||
|
||||
@ -82,21 +84,50 @@ fn resolve_associated_item<'tcx>(
|
||||
// the actual function:
|
||||
match vtbl {
|
||||
traits::VtableImpl(impl_data) => {
|
||||
let (def_id, substs) =
|
||||
traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
|
||||
debug!(
|
||||
"resolving VtableImpl: {:?}, {:?}, {:?}, {:?}",
|
||||
param_env, trait_item, rcvr_substs, impl_data
|
||||
);
|
||||
assert!(!rcvr_substs.needs_infer());
|
||||
assert!(!trait_ref.needs_infer());
|
||||
|
||||
let resolved_item = tcx.associated_item(def_id);
|
||||
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
|
||||
let trait_def = tcx.trait_def(trait_def_id);
|
||||
let leaf_def = trait_def
|
||||
.ancestors(tcx, impl_data.impl_def_id)
|
||||
.ok()?
|
||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
|
||||
});
|
||||
let def_id = leaf_def.item.def_id;
|
||||
|
||||
let substs = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = param_env.with_reveal_all();
|
||||
let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(
|
||||
&infcx,
|
||||
param_env,
|
||||
impl_data.impl_def_id,
|
||||
substs,
|
||||
leaf_def.defining_node,
|
||||
);
|
||||
infcx.tcx.erase_regions(&substs)
|
||||
});
|
||||
|
||||
// Since this is a trait item, we need to see if the item is either a trait default item
|
||||
// or a specialization because we can't resolve those unless we can `Reveal::All`.
|
||||
// NOTE: This should be kept in sync with the similar code in
|
||||
// `rustc_middle::traits::project::assemble_candidates_from_impls()`.
|
||||
let eligible = if !resolved_item.defaultness.is_default() {
|
||||
let eligible = if leaf_def.is_final() {
|
||||
// Non-specializable items are always projectable.
|
||||
true
|
||||
} else if param_env.reveal == traits::Reveal::All {
|
||||
!trait_ref.needs_subst()
|
||||
} else {
|
||||
false
|
||||
// Only reveal a specializable default if we're past type-checking
|
||||
// and the obligation is monomorphic, otherwise passes such as
|
||||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
if param_env.reveal == Reveal::All { !trait_ref.needs_subst() } else { false }
|
||||
};
|
||||
|
||||
if !eligible {
|
||||
|
@ -165,6 +165,16 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
|
||||
)
|
||||
}
|
||||
|
||||
fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
|
||||
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
|
||||
let item = tcx.hir().expect_item(hir_id);
|
||||
if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
|
||||
defaultness
|
||||
} else {
|
||||
bug!("`impl_defaultness` called on {:?}", item);
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the `Sized` constraint.
|
||||
///
|
||||
/// In fact, there are only a few options for the types in the constraint:
|
||||
@ -371,6 +381,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
crate_hash,
|
||||
instance_def_size_estimate,
|
||||
issue33140_self_ty,
|
||||
impl_defaultness,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -1942,7 +1942,7 @@ fn check_specialization_validity<'tcx>(
|
||||
// grandparent. In that case, if parent is a `default impl`, inherited items use the
|
||||
// "defaultness" from the grandparent, else they are final.
|
||||
None => {
|
||||
if traits::impl_is_default(tcx, parent_impl.def_id()) {
|
||||
if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
|
||||
None
|
||||
} else {
|
||||
Some(Err(parent_impl.def_id()))
|
||||
@ -2114,10 +2114,10 @@ fn check_impl_items_against_trait<'tcx>(
|
||||
for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
|
||||
let is_implemented = ancestors
|
||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
||||
.map(|node_item| !node_item.node.is_from_trait())
|
||||
.map(|node_item| !node_item.defining_node.is_from_trait())
|
||||
.unwrap_or(false);
|
||||
|
||||
if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
|
||||
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
|
||||
if !trait_item.defaultness.has_value() {
|
||||
missing_items.push(*trait_item);
|
||||
}
|
||||
|
@ -5,7 +5,8 @@ LL | unsafe { std::mem::transmute(()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| transmuting to uninhabited type
|
||||
| inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26
|
||||
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
|
||||
| inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
|
||||
...
|
||||
LL | const FOO: [Empty; 3] = [foo(); 3];
|
||||
| -----------------------------------
|
||||
|
@ -17,7 +17,8 @@ LL | my_fn();
|
||||
| ^^^^^^^
|
||||
| |
|
||||
| calling a function with ABI C using caller ABI Rust
|
||||
| inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17
|
||||
| inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
|
||||
| inside `VAL` at $DIR/abi-mismatch.rs:13:17
|
||||
...
|
||||
LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
|
||||
| --------------------------------------------------------------------------------------
|
||||
|
@ -12,12 +12,15 @@ LL | | // Code here does not matter - this is replaced by the
|
||||
LL | | // real drop glue by the compiler.
|
||||
LL | | drop_in_place(to_drop)
|
||||
LL | | }
|
||||
| |_^ calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
|
||||
| | ^
|
||||
| | |
|
||||
| |_calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
|
||||
| inside `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
||||
|
|
||||
::: $DIR/drop.rs:23:1
|
||||
|
|
||||
LL | };
|
||||
| - inside call to `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
|
||||
| - inside `TEST_BAD` at $DIR/drop.rs:23:1
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,7 +5,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| ptr_offset_from cannot compute offset of pointers into different allocations.
|
||||
| inside call to `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:22:27
|
||||
| inside `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
|
||||
| inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:22:27
|
||||
|
|
||||
::: $DIR/offset_from_ub.rs:16:1
|
||||
|
|
||||
@ -27,7 +28,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| unable to turn bytes into a pointer
|
||||
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:28:14
|
||||
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
|
||||
| inside `NOT_PTR` at $DIR/offset_from_ub.rs:28:14
|
||||
|
|
||||
::: $DIR/offset_from_ub.rs:26:1
|
||||
|
|
||||
@ -44,7 +46,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| exact_div: 1isize cannot be divided by 2isize without remainder
|
||||
| inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:36:14
|
||||
| inside `std::ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
|
||||
| inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:36:14
|
||||
|
|
||||
::: $DIR/offset_from_ub.rs:31:1
|
||||
|
|
||||
@ -64,7 +67,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| invalid use of NULL pointer
|
||||
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:42:14
|
||||
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
|
||||
| inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:42:14
|
||||
|
|
||||
::: $DIR/offset_from_ub.rs:39:1
|
||||
|
|
||||
@ -82,7 +86,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| unable to turn bytes into a pointer
|
||||
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:49:14
|
||||
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
|
||||
| inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:49:14
|
||||
|
|
||||
::: $DIR/offset_from_ub.rs:45:1
|
||||
|
|
||||
|
@ -4,76 +4,140 @@ error[E0080]: evaluation of constant value failed
|
||||
LL | hint_unreachable()
|
||||
| ------------------
|
||||
| |
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
| inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||
...
|
||||
LL | fake_type()
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| reached the configured maximum number of stack frames
|
||||
| inside call to `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/uninhabited-const-issue-61744.rs:12:36
|
||||
|
23
src/test/ui/specialization/issue-70442.rs
Normal file
23
src/test/ui/specialization/issue-70442.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#![feature(specialization)]
|
||||
|
||||
// check-pass
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T> Trait for T {
|
||||
default type Assoc = bool;
|
||||
}
|
||||
|
||||
// This impl inherits the `Assoc` definition from above and "locks it in", or finalizes it, making
|
||||
// child impls unable to further specialize it. However, since the specialization graph didn't
|
||||
// correctly track this, we would refuse to project `Assoc` from this impl, even though that should
|
||||
// happen for items that are final.
|
||||
impl Trait for () {}
|
||||
|
||||
fn foo<X: Trait<Assoc=bool>>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<()>(); // `<() as Trait>::Assoc` is normalized to `bool` correctly
|
||||
}
|
@ -58,13 +58,6 @@ const TEST_REPOS: &'static [Test] = &[
|
||||
// This takes much less time to build than all of Servo and supports stable Rust.
|
||||
packages: &["selectors"],
|
||||
},
|
||||
Test {
|
||||
name: "webrender",
|
||||
repo: "https://github.com/servo/webrender",
|
||||
sha: "a3d6e6894c5a601fa547c6273eb963ca1321c2bb",
|
||||
lock: None,
|
||||
packages: &[],
|
||||
},
|
||||
];
|
||||
|
||||
fn main() {
|
||||
|
@ -180,29 +180,25 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
|
||||
}
|
||||
|
||||
fn print_diff(expected: &str, actual: &str, context_size: usize) {
|
||||
write_diff(expected, actual, context_size, std::io::stdout());
|
||||
}
|
||||
|
||||
fn write_diff(expected: &str, actual: &str, context_size: usize, mut dest: impl io::Write) {
|
||||
let diff_results = make_diff(expected, actual, context_size);
|
||||
for result in diff_results {
|
||||
let mut line_number = result.line_number;
|
||||
for line in result.lines {
|
||||
match line {
|
||||
DiffLine::Expected(e) => {
|
||||
writeln!(dest, "-\t{}", e).unwrap();
|
||||
println!("-\t{}", e);
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Context(c) => {
|
||||
writeln!(dest, "{}\t{}", line_number, c).unwrap();
|
||||
println!("{}\t{}", line_number, c);
|
||||
line_number += 1;
|
||||
}
|
||||
DiffLine::Resulting(r) => {
|
||||
writeln!(dest, "+\t{}", r).unwrap();
|
||||
println!("+\t{}", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln!(dest).unwrap();
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user