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
36 changed files with 410 additions and 362 deletions
|
|
@ -79,7 +79,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match layout.fields {
|
match layout.fields {
|
||||||
layout::FieldPlacement::Union(_) => {
|
layout::FieldsShape::Union(_) => {
|
||||||
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
|
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
|
||||||
let packed = false;
|
let packed = false;
|
||||||
match name {
|
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)
|
cx.type_array(layout.field(cx, 0).llvm_type(cx), count)
|
||||||
}
|
}
|
||||||
layout::FieldPlacement::Arbitrary { .. } => match name {
|
layout::FieldsShape::Arbitrary { .. } => match name {
|
||||||
None => {
|
None => {
|
||||||
let (llfields, packed) = struct_llfields(cx, layout);
|
let (llfields, packed) = struct_llfields(cx, layout);
|
||||||
cx.type_struct(&llfields, packed)
|
cx.type_struct(&llfields, packed)
|
||||||
|
|
@ -371,13 +371,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match self.fields {
|
match self.fields {
|
||||||
layout::FieldPlacement::Union(_) => {
|
layout::FieldsShape::Union(_) => {
|
||||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
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
|
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 {
|
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() {
|
if self.layout.is_unsized() {
|
||||||
assert_eq!(count, 0);
|
assert_eq!(count, 0);
|
||||||
self.llextra.unwrap()
|
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:
|
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:
|
This will work:
|
||||||
|
|
||||||
```
|
```
|
||||||
#[macro_use(debug_assert)]
|
#[macro_use(debug_assert)] // ok!
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
mod foo {
|
mod foo {
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,8 @@ pub struct ConstEvalErr<'tcx> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FrameInfo<'tcx> {
|
pub struct FrameInfo<'tcx> {
|
||||||
/// This span is in the caller.
|
|
||||||
pub call_site: Span,
|
|
||||||
pub instance: ty::Instance<'tcx>,
|
pub instance: ty::Instance<'tcx>,
|
||||||
|
pub span: Span,
|
||||||
pub lint_root: Option<hir::HirId>,
|
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
|
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
|
||||||
== DefPathData::ClosureExpr
|
== DefPathData::ClosureExpr
|
||||||
{
|
{
|
||||||
write!(f, "inside call to closure")?;
|
write!(f, "inside closure")?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "inside call to `{}`", self.instance)?;
|
write!(f, "inside `{}`", self.instance)?;
|
||||||
}
|
}
|
||||||
if !self.call_site.is_dummy() {
|
if !self.span.is_dummy() {
|
||||||
let lo = tcx.sess.source_map().lookup_char_pos(self.call_site.lo());
|
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)?;
|
write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -168,13 +167,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
|
||||||
if let Some(span_msg) = span_msg {
|
if let Some(span_msg) = span_msg {
|
||||||
err.span_label(self.span, span_msg);
|
err.span_label(self.span, span_msg);
|
||||||
}
|
}
|
||||||
// Add spans for the stacktrace.
|
// Add spans for the stacktrace. Don't print a single-line backtrace though.
|
||||||
// Skip the last, which is just the environment of the constant. The stacktrace
|
if self.stacktrace.len() > 1 {
|
||||||
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
|
for frame_info in &self.stacktrace {
|
||||||
// on constant values.
|
err.span_label(frame_info.span, frame_info.to_string());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Let the caller finish the job.
|
// Let the caller finish the job.
|
||||||
|
|
|
||||||
|
|
@ -154,14 +154,44 @@ impl Iterator for Ancestors<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NodeItem<T> {
|
/// Information about the most specialized definition of an associated item.
|
||||||
pub node: Node,
|
pub struct LeafDef {
|
||||||
pub item: T,
|
/// 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> {
|
impl LeafDef {
|
||||||
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
|
/// Returns whether this definition is known to not be further specializable.
|
||||||
NodeItem { node: self.node, item: f(self.item) }
|
pub fn is_final(&self) -> bool {
|
||||||
|
self.finalizing_node.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,18 +203,36 @@ impl<'tcx> Ancestors<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_item_name: Ident,
|
trait_item_name: Ident,
|
||||||
trait_item_kind: ty::AssocKind,
|
trait_item_kind: ty::AssocKind,
|
||||||
) -> Option<NodeItem<ty::AssocItem>> {
|
) -> Option<LeafDef> {
|
||||||
let trait_def_id = self.trait_def_id;
|
let trait_def_id = self.trait_def_id;
|
||||||
|
let mut finalizing_node = None;
|
||||||
|
|
||||||
self.find_map(|node| {
|
self.find_map(|node| {
|
||||||
node.item(tcx, trait_item_name, trait_item_kind, trait_def_id)
|
if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) {
|
||||||
.map(|item| NodeItem { node, item })
|
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
|
/// Walk up the specialization ancestors of a given impl, starting with that
|
||||||
/// impl itself. Returns `None` if an error was reported while building the
|
/// impl itself.
|
||||||
/// specialization graph.
|
///
|
||||||
|
/// Returns `Err` if an error was reported while building the specialization
|
||||||
|
/// graph.
|
||||||
pub fn ancestors(
|
pub fn ancestors(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ enum StructKind {
|
||||||
// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
|
// 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)
|
// This is used to go between `memory_index` (source field order to memory order)
|
||||||
// and `inverse_memory_index` (memory order to source field 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.
|
// FIXME(eddyb) build a better abstraction for permutations, if possible.
|
||||||
fn invert_mapping(map: &[u32]) -> Vec<u32> {
|
fn invert_mapping(map: &[u32]) -> Vec<u32> {
|
||||||
let mut inverse = vec![0; map.len()];
|
let mut inverse = vec![0; map.len()];
|
||||||
|
|
@ -257,7 +257,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
Layout {
|
Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldPlacement::Arbitrary {
|
fields: FieldsShape::Arbitrary {
|
||||||
offsets: vec![Size::ZERO, b_offset],
|
offsets: vec![Size::ZERO, b_offset],
|
||||||
memory_index: vec![0, 1],
|
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 = self.scalar_pair(a.clone(), b.clone());
|
||||||
let pair_offsets = match pair.fields {
|
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]);
|
assert_eq!(memory_index, &[0, 1]);
|
||||||
offsets
|
offsets
|
||||||
}
|
}
|
||||||
|
|
@ -471,7 +471,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
Ok(Layout {
|
Ok(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldPlacement::Arbitrary { offsets, memory_index },
|
fields: FieldsShape::Arbitrary { offsets, memory_index },
|
||||||
abi,
|
abi,
|
||||||
largest_niche,
|
largest_niche,
|
||||||
align,
|
align,
|
||||||
|
|
@ -520,7 +520,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
// The never type.
|
// The never type.
|
||||||
ty::Never => tcx.intern_layout(Layout {
|
ty::Never => tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldPlacement::Union(0),
|
fields: FieldsShape::Union(0),
|
||||||
abi: Abi::Uninhabited,
|
abi: Abi::Uninhabited,
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align: dl.i8_align,
|
align: dl.i8_align,
|
||||||
|
|
@ -581,7 +581,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
tcx.intern_layout(Layout {
|
tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldPlacement::Array { stride: element.size, count },
|
fields: FieldsShape::Array { stride: element.size, count },
|
||||||
abi,
|
abi,
|
||||||
largest_niche,
|
largest_niche,
|
||||||
align: element.align,
|
align: element.align,
|
||||||
|
|
@ -592,7 +592,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
let element = self.layout_of(element)?;
|
let element = self.layout_of(element)?;
|
||||||
tcx.intern_layout(Layout {
|
tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
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 },
|
abi: Abi::Aggregate { sized: false },
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align: element.align,
|
align: element.align,
|
||||||
|
|
@ -601,7 +601,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
ty::Str => tcx.intern_layout(Layout {
|
ty::Str => tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
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 },
|
abi: Abi::Aggregate { sized: false },
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align: dl.i8_align,
|
align: dl.i8_align,
|
||||||
|
|
@ -670,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
tcx.intern_layout(Layout {
|
tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
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 },
|
abi: Abi::Vector { element: scalar, count },
|
||||||
largest_niche: element.largest_niche.clone(),
|
largest_niche: element.largest_niche.clone(),
|
||||||
size,
|
size,
|
||||||
|
|
@ -746,7 +746,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
return Ok(tcx.intern_layout(Layout {
|
return Ok(tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index },
|
variants: Variants::Single { index },
|
||||||
fields: FieldPlacement::Union(variants[index].len()),
|
fields: FieldsShape::Union(variants[index].len()),
|
||||||
abi,
|
abi,
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align,
|
align,
|
||||||
|
|
@ -980,7 +980,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
discr_index: 0,
|
discr_index: 0,
|
||||||
variants: st,
|
variants: st,
|
||||||
},
|
},
|
||||||
fields: FieldPlacement::Arbitrary {
|
fields: FieldsShape::Arbitrary {
|
||||||
offsets: vec![offset],
|
offsets: vec![offset],
|
||||||
memory_index: vec![0],
|
memory_index: vec![0],
|
||||||
},
|
},
|
||||||
|
|
@ -1121,7 +1121,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
let new_ity_size = ity.size();
|
let new_ity_size = ity.size();
|
||||||
for variant in &mut layout_variants {
|
for variant in &mut layout_variants {
|
||||||
match variant.fields {
|
match variant.fields {
|
||||||
FieldPlacement::Arbitrary { ref mut offsets, .. } => {
|
FieldsShape::Arbitrary { ref mut offsets, .. } => {
|
||||||
for i in offsets {
|
for i in offsets {
|
||||||
if *i <= old_ity_size {
|
if *i <= old_ity_size {
|
||||||
assert_eq!(*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;
|
let mut common_prim = None;
|
||||||
for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
|
for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
|
||||||
let offsets = match layout_variant.fields {
|
let offsets = match layout_variant.fields {
|
||||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets,
|
FieldsShape::Arbitrary { ref offsets, .. } => offsets,
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let mut fields =
|
let mut fields =
|
||||||
|
|
@ -1187,7 +1187,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
if let Some((prim, offset)) = common_prim {
|
if let Some((prim, offset)) = common_prim {
|
||||||
let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
|
let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
|
||||||
let pair_offsets = match pair.fields {
|
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]);
|
assert_eq!(memory_index, &[0, 1]);
|
||||||
offsets
|
offsets
|
||||||
}
|
}
|
||||||
|
|
@ -1218,7 +1218,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
discr_index: 0,
|
discr_index: 0,
|
||||||
variants: layout_variants,
|
variants: layout_variants,
|
||||||
},
|
},
|
||||||
fields: FieldPlacement::Arbitrary {
|
fields: FieldsShape::Arbitrary {
|
||||||
offsets: vec![Size::ZERO],
|
offsets: vec![Size::ZERO],
|
||||||
memory_index: vec![0],
|
memory_index: vec![0],
|
||||||
},
|
},
|
||||||
|
|
@ -1435,7 +1435,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
// GeneratorLayout.
|
// GeneratorLayout.
|
||||||
debug!("prefix = {:#?}", prefix);
|
debug!("prefix = {:#?}", prefix);
|
||||||
let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
|
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);
|
let mut inverse_memory_index = invert_mapping(&memory_index);
|
||||||
|
|
||||||
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
|
// "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 memory_index_b = invert_mapping(&inverse_memory_index_b);
|
||||||
|
|
||||||
let outer_fields =
|
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)
|
(outer_fields, offsets_b, memory_index_b)
|
||||||
}
|
}
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
|
|
@ -1492,7 +1492,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
variant.variants = Variants::Single { index };
|
variant.variants = Variants::Single { index };
|
||||||
|
|
||||||
let (offsets, memory_index) = match variant.fields {
|
let (offsets, memory_index) = match variant.fields {
|
||||||
FieldPlacement::Arbitrary { offsets, memory_index } => (offsets, memory_index),
|
FieldsShape::Arbitrary { offsets, memory_index } => (offsets, memory_index),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1535,7 +1535,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
|
combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
|
||||||
let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
|
let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
|
||||||
|
|
||||||
variant.fields = FieldPlacement::Arbitrary {
|
variant.fields = FieldsShape::Arbitrary {
|
||||||
offsets: combined_offsets,
|
offsets: combined_offsets,
|
||||||
memory_index: combined_memory_index,
|
memory_index: combined_memory_index,
|
||||||
};
|
};
|
||||||
|
|
@ -1990,7 +1990,7 @@ where
|
||||||
if index == variant_index &&
|
if index == variant_index &&
|
||||||
// Don't confuse variants of uninhabited enums with the enum itself.
|
// Don't confuse variants of uninhabited enums with the enum itself.
|
||||||
// For more details see https://github.com/rust-lang/rust/issues/69763.
|
// For more details see https://github.com/rust-lang/rust/issues/69763.
|
||||||
this.fields != FieldPlacement::Union(0) =>
|
this.fields != FieldsShape::Union(0) =>
|
||||||
{
|
{
|
||||||
this.layout
|
this.layout
|
||||||
}
|
}
|
||||||
|
|
@ -2008,7 +2008,7 @@ where
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
tcx.intern_layout(Layout {
|
tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: variant_index },
|
variants: Variants::Single { index: variant_index },
|
||||||
fields: FieldPlacement::Union(fields),
|
fields: FieldsShape::Union(fields),
|
||||||
abi: Abi::Uninhabited,
|
abi: Abi::Uninhabited,
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align: tcx.data_layout.i8_align,
|
align: tcx.data_layout.i8_align,
|
||||||
|
|
@ -2054,7 +2054,7 @@ where
|
||||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||||
// This provides information about, e.g., DST struct pointees
|
// This provides information about, e.g., DST struct pointees
|
||||||
// (which may have no non-DST form), and will work as long
|
// (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 {
|
if i == 0 {
|
||||||
let nil = tcx.mk_unit();
|
let nil = tcx.mk_unit();
|
||||||
let ptr_ty = if this.ty.is_unsafe_ptr() {
|
let ptr_ty = if this.ty.is_unsafe_ptr() {
|
||||||
|
|
@ -2219,7 +2219,7 @@ where
|
||||||
|
|
||||||
if let Some(variant) = data_variant {
|
if let Some(variant) = data_variant {
|
||||||
// We're not interested in any unions.
|
// We're not interested in any unions.
|
||||||
if let FieldPlacement::Union(_) = variant.fields {
|
if let FieldsShape::Union(_) = variant.fields {
|
||||||
data_variant = None;
|
data_variant = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,6 @@ pub fn error_to_const_error<'mir, 'tcx, M: Machine<'mir, 'tcx>>(
|
||||||
mut error: InterpErrorInfo<'tcx>,
|
mut error: InterpErrorInfo<'tcx>,
|
||||||
) -> ConstEvalErr<'tcx> {
|
) -> ConstEvalErr<'tcx> {
|
||||||
error.print_backtrace();
|
error.print_backtrace();
|
||||||
let stacktrace = ecx.generate_stacktrace(None);
|
let stacktrace = ecx.generate_stacktrace();
|
||||||
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
|
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||||
|
|
||||||
ecx.push_stack_frame(
|
ecx.push_stack_frame(
|
||||||
cid.instance,
|
cid.instance,
|
||||||
body.span,
|
|
||||||
body,
|
body,
|
||||||
Some(ret.into()),
|
Some(ret.into()),
|
||||||
StackPopCleanup::None { cleanup: false },
|
StackPopCleanup::None { cleanup: false },
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ use std::hash::Hash;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
|
||||||
use rustc_ast::ast::Mutability;
|
use rustc_ast::ast::Mutability;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::AssertMessage;
|
use rustc_middle::mir::AssertMessage;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{def_id::DefId, Span};
|
|
||||||
|
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
|
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.
|
/// If this returns successfully (`Ok`), the function should just be evaluated normally.
|
||||||
fn hook_panic_fn(
|
fn hook_panic_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx>],
|
args: &[OpTy<'tcx>],
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
|
@ -77,7 +76,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> {
|
||||||
|
|
||||||
let msg_place = self.deref_operand(args[0])?;
|
let msg_place = self.deref_operand(args[0])?;
|
||||||
let msg = Symbol::intern(self.read_str(msg_place)?);
|
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);
|
let (file, line, col) = self.location_triple_for_span(span);
|
||||||
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
|
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -191,7 +190,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx>],
|
args: &[OpTy<'tcx>],
|
||||||
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
||||||
|
|
@ -213,7 +211,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||||
} else {
|
} else {
|
||||||
// Some functions we support even if they are non-const -- but avoid testing
|
// Some functions we support even if they are non-const -- but avoid testing
|
||||||
// that for const fn!
|
// 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
|
// We certainly do *not* want to actually call the fn
|
||||||
// though, so be sure we return here.
|
// though, so be sure we return here.
|
||||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||||
|
|
@ -248,13 +246,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
|
||||||
|
|
||||||
fn call_intrinsic(
|
fn call_intrinsic(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx>],
|
args: &[OpTy<'tcx>],
|
||||||
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
|
||||||
_unwind: Option<mir::BasicBlock>,
|
_unwind: Option<mir::BasicBlock>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
if ecx.emulate_intrinsic(span, instance, args, ret)? {
|
if ecx.emulate_intrinsic(instance, args, ret)? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// An intrinsic that we do not support
|
// 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::query::TyCtxtAt;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
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::{
|
use super::{
|
||||||
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
|
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.
|
/// The def_id and substs of the current function.
|
||||||
pub instance: ty::Instance<'tcx>,
|
pub instance: ty::Instance<'tcx>,
|
||||||
|
|
||||||
/// The span of the call site.
|
|
||||||
pub span: source_map::Span,
|
|
||||||
|
|
||||||
/// Extra data for the machine.
|
/// Extra data for the machine.
|
||||||
pub extra: Extra,
|
pub extra: Extra,
|
||||||
|
|
||||||
|
|
@ -502,7 +499,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
pub fn push_stack_frame(
|
pub fn push_stack_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
span: Span,
|
|
||||||
body: &'mir mir::Body<'tcx>,
|
body: &'mir mir::Body<'tcx>,
|
||||||
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
|
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
|
||||||
return_to_block: StackPopCleanup,
|
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
|
// empty local array, we fill it in below, after we are inside the stack frame and
|
||||||
// all methods actually know about the frame
|
// all methods actually know about the frame
|
||||||
locals: IndexVec::new(),
|
locals: IndexVec::new(),
|
||||||
span,
|
|
||||||
instance,
|
instance,
|
||||||
stmt: 0,
|
stmt: 0,
|
||||||
extra,
|
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
|
// statics and constants don't have `Storage*` statements, no need to look for them
|
||||||
Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {}
|
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 block in body.basic_blocks() {
|
||||||
for stmt in block.statements.iter() {
|
for stmt in block.statements.iter() {
|
||||||
use rustc_middle::mir::StatementKind::{StorageDead, StorageLive};
|
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>> {
|
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
|
||||||
let mut last_span = None;
|
|
||||||
let mut frames = Vec::new();
|
let mut frames = Vec::new();
|
||||||
for frame in self.stack().iter().rev() {
|
for frame in self.stack().iter().rev() {
|
||||||
// make sure we don't emit frames that are duplicates of the previous
|
let source_info = frame.current_source_info();
|
||||||
if explicit_span == Some(frame.span) {
|
let lint_root = source_info.and_then(|source_info| {
|
||||||
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| {
|
|
||||||
match &frame.body.source_scopes[source_info.scope].local_data {
|
match &frame.body.source_scopes[source_info.scope].local_data {
|
||||||
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
|
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
|
||||||
mir::ClearCrossCrate::Clear => None,
|
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
|
frames
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -899,7 +881,6 @@ where
|
||||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
|
||||||
self.body.hash_stable(hcx, hasher);
|
self.body.hash_stable(hcx, hasher);
|
||||||
self.instance.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_to_block.hash_stable(hcx, hasher);
|
||||||
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
|
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
|
||||||
self.locals.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::subst::SubstsRef;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::Span;
|
|
||||||
|
|
||||||
use super::{ImmTy, InterpCx, Machine, OpTy, PlaceTy};
|
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.
|
/// Returns `true` if emulation happened.
|
||||||
pub fn emulate_intrinsic(
|
pub fn emulate_intrinsic(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx, M::PointerTag>],
|
args: &[OpTy<'tcx, M::PointerTag>],
|
||||||
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
|
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`
|
// `src/librustc_middle/ty/constness.rs`
|
||||||
match intrinsic_name {
|
match intrinsic_name {
|
||||||
sym::caller_location => {
|
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);
|
let location = self.alloc_caller_location_for_span(span);
|
||||||
self.write_scalar(location.ptr, dest)?;
|
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::needs_drop => self.tcx.types.bool,
|
||||||
sym::type_id => self.tcx.types.u64,
|
sym::type_id => self.tcx.types.u64,
|
||||||
sym::type_name => self.tcx.mk_static_str(),
|
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)?;
|
let val = self.const_eval(gid, ty)?;
|
||||||
self.copy_op(val, dest)?;
|
self.copy_op(val, dest)?;
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,21 @@ use crate::interpret::{
|
||||||
|
|
||||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
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
|
/// 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
|
/// frame which is not `#[track_caller]`.
|
||||||
/// `None` is returned and the callsite of the function invocation itself should be used.
|
crate fn find_closest_untracked_caller_location(&self) -> Span {
|
||||||
crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
|
self.stack
|
||||||
let mut caller_span = None;
|
.iter()
|
||||||
for next_caller in self.stack.iter().rev() {
|
.rev()
|
||||||
if !next_caller.instance.def.requires_caller_location(*self.tcx) {
|
// Find first non-`#[track_caller]` frame.
|
||||||
return caller_span;
|
.find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
|
||||||
}
|
// Assert that there is always such a frame.
|
||||||
caller_span = Some(next_caller.span);
|
.unwrap()
|
||||||
}
|
.current_source_info()
|
||||||
|
// Assert that the frame we look at is actually executing code currently
|
||||||
caller_span
|
// (`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.
|
/// 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::mir;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_span::{def_id::DefId, Span};
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
|
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
|
||||||
|
|
@ -135,7 +135,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||||
/// was used.
|
/// was used.
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||||
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
|
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.
|
/// responsibility to advance the instruction pointer as appropriate.
|
||||||
fn call_intrinsic(
|
fn call_intrinsic(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
span: Span,
|
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||||
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
|
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,
|
// Go through the layout. There are lots of types that support a length,
|
||||||
// e.g., SIMD types.
|
// e.g., SIMD types.
|
||||||
match self.layout.fields {
|
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),
|
_ => bug!("len not supported on sized type {:?}", self.layout.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,7 +437,7 @@ where
|
||||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
// Not using the layout method because we want to compute on u64
|
// Not using the layout method because we want to compute on u64
|
||||||
match base.layout.fields {
|
match base.layout.fields {
|
||||||
layout::FieldPlacement::Array { stride, .. } => {
|
layout::FieldsShape::Array { stride, .. } => {
|
||||||
let len = base.len(self)?;
|
let len = base.len(self)?;
|
||||||
if index >= len {
|
if index >= len {
|
||||||
// This can only be reached in ConstProp and non-rustc-MIR.
|
// 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 len = base.len(self)?; // also asserts that we have a type where this makes sense
|
||||||
let stride = match base.layout.fields {
|
let stride = match base.layout.fields {
|
||||||
layout::FieldPlacement::Array { stride, .. } => stride,
|
layout::FieldsShape::Array { stride, .. } => stride,
|
||||||
_ => bug!("mplace_array_fields: expected an array layout"),
|
_ => bug!("mplace_array_fields: expected an array layout"),
|
||||||
};
|
};
|
||||||
let layout = base.layout.field(self, 0)?;
|
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
|
// Not using layout method because that works with usize, and does not work with slices
|
||||||
// (that have count 0 in their layout).
|
// (that have count 0 in their layout).
|
||||||
let from_offset = match base.layout.fields {
|
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),
|
_ => 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::layout::{self, LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::Instance;
|
use rustc_middle::ty::Instance;
|
||||||
use rustc_middle::{mir, ty};
|
use rustc_middle::{mir, ty};
|
||||||
use rustc_span::source_map::Span;
|
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use super::{
|
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)),
|
Some((dest, ret)) => Some((self.eval_place(dest)?, ret)),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
self.eval_fn_call(
|
self.eval_fn_call(fn_val, abi, &args[..], ret, *cleanup)?;
|
||||||
fn_val,
|
|
||||||
terminator.source_info.span,
|
|
||||||
abi,
|
|
||||||
&args[..],
|
|
||||||
ret,
|
|
||||||
*cleanup,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Drop { location, target, unwind } => {
|
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);
|
trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
|
||||||
|
|
||||||
let instance = Instance::resolve_drop_in_place(*self.tcx, 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 } => {
|
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(
|
fn eval_fn_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
fn_val: FnVal<'tcx, M::ExtraFnVal>,
|
fn_val: FnVal<'tcx, M::ExtraFnVal>,
|
||||||
span: Span,
|
|
||||||
caller_abi: Abi,
|
caller_abi: Abi,
|
||||||
args: &[OpTy<'tcx, M::PointerTag>],
|
args: &[OpTy<'tcx, M::PointerTag>],
|
||||||
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
|
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 {
|
match instance.def {
|
||||||
ty::InstanceDef::Intrinsic(..) => {
|
ty::InstanceDef::Intrinsic(..) => {
|
||||||
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
|
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::VtableShim(..)
|
||||||
| ty::InstanceDef::ReifyShim(..)
|
| ty::InstanceDef::ReifyShim(..)
|
||||||
|
|
@ -252,14 +243,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
| ty::InstanceDef::CloneShim(..)
|
| ty::InstanceDef::CloneShim(..)
|
||||||
| ty::InstanceDef::Item(_) => {
|
| ty::InstanceDef::Item(_) => {
|
||||||
// We need MIR for this fn
|
// 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,
|
Some(body) => body,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.push_stack_frame(
|
self.push_stack_frame(
|
||||||
instance,
|
instance,
|
||||||
span,
|
|
||||||
body,
|
body,
|
||||||
ret.map(|p| p.0),
|
ret.map(|p| p.0),
|
||||||
StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
|
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() });
|
OpTy::from(ImmTy { layout: this_receiver_ptr, imm: receiver_place.ptr.into() });
|
||||||
trace!("Patched self operand to {:#?}", args[0]);
|
trace!("Patched self operand to {:#?}", args[0]);
|
||||||
// recurse with concrete function
|
// 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,
|
&mut self,
|
||||||
place: PlaceTy<'tcx, M::PointerTag>,
|
place: PlaceTy<'tcx, M::PointerTag>,
|
||||||
instance: ty::Instance<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
span: Span,
|
|
||||||
target: mir::BasicBlock,
|
target: mir::BasicBlock,
|
||||||
unwind: Option<mir::BasicBlock>,
|
unwind: Option<mir::BasicBlock>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
|
@ -444,7 +433,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
|
||||||
self.eval_fn_call(
|
self.eval_fn_call(
|
||||||
FnVal::Instance(instance),
|
FnVal::Instance(instance),
|
||||||
span,
|
|
||||||
Abi::Rust,
|
Abi::Rust,
|
||||||
&[arg.into()],
|
&[arg.into()],
|
||||||
Some((dest.into(), target)),
|
Some((dest.into(), target)),
|
||||||
|
|
|
||||||
|
|
@ -207,10 +207,10 @@ macro_rules! make_value_visitor {
|
||||||
|
|
||||||
// Visit the fields of this value.
|
// Visit the fields of this value.
|
||||||
match v.layout().fields {
|
match v.layout().fields {
|
||||||
layout::FieldPlacement::Union(fields) => {
|
layout::FieldsShape::Union(fields) => {
|
||||||
self.visit_union(v, 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
|
// FIXME: We collect in a vec because otherwise there are lifetime
|
||||||
// errors: Projecting to a field needs access to `ecx`.
|
// errors: Projecting to a field needs access to `ecx`.
|
||||||
let fields: Vec<InterpResult<'tcx, Self::V>> =
|
let fields: Vec<InterpResult<'tcx, Self::V>> =
|
||||||
|
|
@ -220,7 +220,7 @@ macro_rules! make_value_visitor {
|
||||||
.collect();
|
.collect();
|
||||||
self.visit_aggregate(v, fields.into_iter())?;
|
self.visit_aggregate(v, fields.into_iter())?;
|
||||||
},
|
},
|
||||||
layout::FieldPlacement::Array { .. } => {
|
layout::FieldsShape::Array { .. } => {
|
||||||
// Let's get an mplace first.
|
// Let's get an mplace first.
|
||||||
let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
|
let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
|
||||||
// Now we can go over all the fields.
|
// 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(
|
fn find_mir_or_eval_fn(
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
_span: Span,
|
|
||||||
_instance: ty::Instance<'tcx>,
|
_instance: ty::Instance<'tcx>,
|
||||||
_args: &[OpTy<'tcx>],
|
_args: &[OpTy<'tcx>],
|
||||||
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
||||||
|
|
@ -204,7 +203,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
|
|
||||||
fn call_intrinsic(
|
fn call_intrinsic(
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
_span: Span,
|
|
||||||
_instance: ty::Instance<'tcx>,
|
_instance: ty::Instance<'tcx>,
|
||||||
_args: &[OpTy<'tcx>],
|
_args: &[OpTy<'tcx>],
|
||||||
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
||||||
|
|
@ -361,7 +359,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
|
|
||||||
ecx.push_stack_frame(
|
ecx.push_stack_frame(
|
||||||
Instance::new(def_id, substs),
|
Instance::new(def_id, substs),
|
||||||
span,
|
|
||||||
dummy_body,
|
dummy_body,
|
||||||
ret.map(Into::into),
|
ret.map(Into::into),
|
||||||
StackPopCleanup::None { cleanup: false },
|
StackPopCleanup::None { cleanup: false },
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ where
|
||||||
// use of float registers to structures (not unions) containing exactly one or two
|
// use of float registers to structures (not unions) containing exactly one or two
|
||||||
// float fields.
|
// 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 ret.layout.fields.count() == 1 {
|
||||||
if let Some(reg) = float_reg(cx, ret, 0) {
|
if let Some(reg) = float_reg(cx, ret, 0) {
|
||||||
ret.cast_to(reg);
|
ret.cast_to(reg);
|
||||||
|
|
@ -88,15 +88,15 @@ where
|
||||||
let mut prefix_index = 0;
|
let mut prefix_index = 0;
|
||||||
|
|
||||||
match arg.layout.fields {
|
match arg.layout.fields {
|
||||||
abi::FieldPlacement::Array { .. } => {
|
abi::FieldsShape::Array { .. } => {
|
||||||
// Arrays are passed indirectly
|
// Arrays are passed indirectly
|
||||||
arg.make_indirect();
|
arg.make_indirect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
abi::FieldPlacement::Union(_) => {
|
abi::FieldsShape::Union(_) => {
|
||||||
// Unions and are always treated as a series of 64-bit integer chunks
|
// 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
|
// 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.
|
// doubles not part of another aggregate are passed as floats.
|
||||||
let mut last_offset = Size::ZERO;
|
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::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
||||||
use crate::spec::{self, HasTargetSpec};
|
use crate::spec::{self, HasTargetSpec};
|
||||||
|
|
||||||
|
|
@ -315,7 +315,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
start: Size|
|
start: Size|
|
||||||
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
||||||
let is_union = match layout.fields {
|
let is_union = match layout.fields {
|
||||||
FieldPlacement::Array { count, .. } => {
|
FieldsShape::Array { count, .. } => {
|
||||||
assert_eq!(start, Size::ZERO);
|
assert_eq!(start, Size::ZERO);
|
||||||
|
|
||||||
let result = if count > 0 {
|
let result = if count > 0 {
|
||||||
|
|
@ -325,8 +325,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
};
|
};
|
||||||
return Ok((result, layout.size));
|
return Ok((result, layout.size));
|
||||||
}
|
}
|
||||||
FieldPlacement::Union(_) => true,
|
FieldsShape::Union(_) => true,
|
||||||
FieldPlacement::Arbitrary { .. } => false,
|
FieldsShape::Arbitrary { .. } => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = HomogeneousAggregate::NoData;
|
let mut result = HomogeneousAggregate::NoData;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{
|
use crate::abi::{
|
||||||
self, Abi, FieldPlacement, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
|
self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
|
||||||
};
|
};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
|
|
@ -87,12 +87,12 @@ where
|
||||||
},
|
},
|
||||||
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
|
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
|
||||||
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
|
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
|
||||||
FieldPlacement::Union(_) => {
|
FieldsShape::Union(_) => {
|
||||||
if !arg_layout.is_zst() {
|
if !arg_layout.is_zst() {
|
||||||
return Err(CannotUseFpConv);
|
return Err(CannotUseFpConv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FieldPlacement::Array { count, .. } => {
|
FieldsShape::Array { count, .. } => {
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
let elem_layout = arg_layout.field(cx, 0);
|
let elem_layout = arg_layout.field(cx, 0);
|
||||||
should_use_fp_conv_helper(
|
should_use_fp_conv_helper(
|
||||||
|
|
@ -105,7 +105,7 @@ where
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FieldPlacement::Arbitrary { .. } => {
|
FieldsShape::Arbitrary { .. } => {
|
||||||
match arg_layout.variants {
|
match arg_layout.variants {
|
||||||
abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
|
abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
|
||||||
abi::Variants::Single { .. } => (),
|
abi::Variants::Single { .. } => (),
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@ impl Scalar {
|
||||||
|
|
||||||
/// Describes how the fields of a type are located in memory.
|
/// Describes how the fields of a type are located in memory.
|
||||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
#[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.
|
/// All fields start at no offset. The `usize` is the field count.
|
||||||
///
|
///
|
||||||
/// In the case of primitives the number of fields is `0`.
|
/// 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 {
|
pub fn count(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
FieldPlacement::Union(count) => count,
|
FieldsShape::Union(count) => count,
|
||||||
FieldPlacement::Array { count, .. } => {
|
FieldsShape::Array { count, .. } => {
|
||||||
let usize_count = count as usize;
|
let usize_count = count as usize;
|
||||||
assert_eq!(usize_count as u64, count);
|
assert_eq!(usize_count as u64, count);
|
||||||
usize_count
|
usize_count
|
||||||
}
|
}
|
||||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len(),
|
FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self, i: usize) -> Size {
|
pub fn offset(&self, i: usize) -> Size {
|
||||||
match *self {
|
match *self {
|
||||||
FieldPlacement::Union(count) => {
|
FieldsShape::Union(count) => {
|
||||||
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
|
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
|
||||||
Size::ZERO
|
Size::ZERO
|
||||||
}
|
}
|
||||||
FieldPlacement::Array { stride, count } => {
|
FieldsShape::Array { stride, count } => {
|
||||||
let i = u64::try_from(i).unwrap();
|
let i = u64::try_from(i).unwrap();
|
||||||
assert!(i < count);
|
assert!(i < count);
|
||||||
stride * i
|
stride * i
|
||||||
}
|
}
|
||||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i],
|
FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory_index(&self, i: usize) -> usize {
|
pub fn memory_index(&self, i: usize) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
|
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||||
FieldPlacement::Arbitrary { ref memory_index, .. } => {
|
FieldsShape::Arbitrary { ref memory_index, .. } => {
|
||||||
let r = memory_index[i];
|
let r = memory_index[i];
|
||||||
assert_eq!(r as usize as u32, r);
|
assert_eq!(r as usize as u32, r);
|
||||||
r as usize
|
r as usize
|
||||||
|
|
@ -704,7 +704,7 @@ impl FieldPlacement {
|
||||||
let use_small = self.count() <= inverse_small.len();
|
let use_small = self.count() <= inverse_small.len();
|
||||||
|
|
||||||
// We have to write this logic twice in order to keep the array small.
|
// 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 {
|
if use_small {
|
||||||
for i in 0..self.count() {
|
for i in 0..self.count() {
|
||||||
inverse_small[memory_index[i] as usize] = i as u8;
|
inverse_small[memory_index[i] as usize] = i as u8;
|
||||||
|
|
@ -718,8 +718,8 @@ impl FieldPlacement {
|
||||||
}
|
}
|
||||||
|
|
||||||
(0..self.count()).map(move |i| match *self {
|
(0..self.count()).map(move |i| match *self {
|
||||||
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
|
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||||
FieldPlacement::Arbitrary { .. } => {
|
FieldsShape::Arbitrary { .. } => {
|
||||||
if use_small {
|
if use_small {
|
||||||
inverse_small[i] as usize
|
inverse_small[i] as usize
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -888,7 +888,7 @@ impl Niche {
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
/// Says where the fields are located within the layout.
|
/// Says where the fields are located within the layout.
|
||||||
/// Primitives and uninhabited enums appear as unions without fields.
|
/// Primitives and uninhabited enums appear as unions without fields.
|
||||||
pub fields: FieldPlacement,
|
pub fields: FieldsShape,
|
||||||
|
|
||||||
/// Encodes information about multi-variant layouts.
|
/// Encodes information about multi-variant layouts.
|
||||||
/// Even with `Multiple` variants, a layout still has its own fields! Those are then
|
/// 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);
|
let align = scalar.value.align(cx);
|
||||||
Layout {
|
Layout {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldPlacement::Union(0),
|
fields: FieldsShape::Union(0),
|
||||||
abi: Abi::Scalar(scalar),
|
abi: Abi::Scalar(scalar),
|
||||||
largest_niche,
|
largest_niche,
|
||||||
size,
|
size,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ pub use self::project::{
|
||||||
};
|
};
|
||||||
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
|
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
|
||||||
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
|
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::FutureCompatOverlapError;
|
||||||
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
||||||
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
|
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::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
|
||||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
|
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
|
||||||
predicate_for_trait_def, upcast_choices,
|
|
||||||
};
|
};
|
||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
|
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)
|
assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
|
||||||
.map_err(|ErrorReported| ())?;
|
.map_err(|ErrorReported| ())?;
|
||||||
|
|
||||||
let is_default = if node_item.node.is_from_trait() {
|
if node_item.is_final() {
|
||||||
// If true, the impl inherited a `type Foo = Bar`
|
// Non-specializable items are always projectable.
|
||||||
// given in the trait, which is implicitly default.
|
true
|
||||||
// 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
|
|
||||||
} else {
|
} 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
|
// Only reveal a specializable default if we're past type-checking
|
||||||
// and the obligation is monomorphic, otherwise passes such as
|
// and the obligation is monomorphic, otherwise passes such as
|
||||||
// transmute checking and polymorphic MIR optimizations could
|
// transmute checking and polymorphic MIR optimizations could
|
||||||
// get a result which isn't correct for all monomorphizations.
|
// 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
|
// NOTE(eddyb) inference variables can resolve to parameters, so
|
||||||
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
||||||
let poly_trait_ref =
|
let poly_trait_ref =
|
||||||
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
|
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
|
||||||
!poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
|
!poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
|
||||||
}
|
} else {
|
||||||
|
|
||||||
true => {
|
|
||||||
debug!(
|
debug!(
|
||||||
"assemble_candidates_from_impls: not eligible due to default: \
|
"assemble_candidates_from_impls: not eligible due to default: \
|
||||||
assoc_ty={} predicate={}",
|
assoc_ty={} predicate={}",
|
||||||
|
|
@ -1422,7 +1394,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||||
return Progress { ty: tcx.types.err, obligations: nested };
|
return Progress { ty: tcx.types.err, obligations: nested };
|
||||||
}
|
}
|
||||||
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
|
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 ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
|
||||||
let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
||||||
tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
|
tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
|
||||||
|
|
@ -1447,7 +1420,7 @@ fn assoc_ty_def(
|
||||||
selcx: &SelectionContext<'_, '_>,
|
selcx: &SelectionContext<'_, '_>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
assoc_ty_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 tcx = selcx.tcx();
|
||||||
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
|
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;
|
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)
|
if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
|
||||||
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
|
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
|
||||||
{
|
{
|
||||||
return Ok(specialization_graph::NodeItem {
|
return Ok(specialization_graph::LeafDef {
|
||||||
node: specialization_graph::Node::Impl(impl_def_id),
|
|
||||||
item: *item,
|
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_hir::def_id::DefId;
|
||||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
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::COHERENCE_LEAK_CHECK;
|
||||||
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
|
||||||
use rustc_span::DUMMY_SP;
|
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)
|
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`?
|
/// Is `impl1` a specialization of `impl2`?
|
||||||
///
|
///
|
||||||
/// Specialization is determined by the sets of types to which the impls apply;
|
/// Specialization is determined by the sets of types to which the impls apply;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use smallvec::smallvec;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::outlives::Component;
|
use rustc_middle::ty::outlives::Component;
|
||||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
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))
|
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 {
|
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 {
|
pub enum TupleArgumentsFlag {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
use traits::{translate_substs, Reveal};
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
|
@ -82,21 +84,50 @@ fn resolve_associated_item<'tcx>(
|
||||||
// the actual function:
|
// the actual function:
|
||||||
match vtbl {
|
match vtbl {
|
||||||
traits::VtableImpl(impl_data) => {
|
traits::VtableImpl(impl_data) => {
|
||||||
let (def_id, substs) =
|
debug!(
|
||||||
traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
|
"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
|
// 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`.
|
// 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
|
// NOTE: This should be kept in sync with the similar code in
|
||||||
// `rustc_middle::traits::project::assemble_candidates_from_impls()`.
|
// `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
|
true
|
||||||
} else if param_env.reveal == traits::Reveal::All {
|
|
||||||
!trait_ref.needs_subst()
|
|
||||||
} else {
|
} 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 {
|
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.
|
/// Calculates the `Sized` constraint.
|
||||||
///
|
///
|
||||||
/// In fact, there are only a few options for the types in the 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,
|
crate_hash,
|
||||||
instance_def_size_estimate,
|
instance_def_size_estimate,
|
||||||
issue33140_self_ty,
|
issue33140_self_ty,
|
||||||
|
impl_defaultness,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1942,7 +1942,7 @@ fn check_specialization_validity<'tcx>(
|
||||||
// grandparent. In that case, if parent is a `default impl`, inherited items use the
|
// grandparent. In that case, if parent is a `default impl`, inherited items use the
|
||||||
// "defaultness" from the grandparent, else they are final.
|
// "defaultness" from the grandparent, else they are final.
|
||||||
None => {
|
None => {
|
||||||
if traits::impl_is_default(tcx, parent_impl.def_id()) {
|
if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Err(parent_impl.def_id()))
|
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() {
|
for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
|
||||||
let is_implemented = ancestors
|
let is_implemented = ancestors
|
||||||
.leaf_def(tcx, trait_item.ident, trait_item.kind)
|
.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);
|
.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() {
|
if !trait_item.defaultness.has_value() {
|
||||||
missing_items.push(*trait_item);
|
missing_items.push(*trait_item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ LL | unsafe { std::mem::transmute(()) }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| transmuting to uninhabited type
|
| 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];
|
LL | const FOO: [Empty; 3] = [foo(); 3];
|
||||||
| -----------------------------------
|
| -----------------------------------
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ LL | my_fn();
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
| |
|
| |
|
||||||
| calling a function with ABI C using caller ABI Rust
|
| 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()) });
|
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 | | // real drop glue by the compiler.
|
||||||
LL | | drop_in_place(to_drop)
|
LL | | drop_in_place(to_drop)
|
||||||
LL | | }
|
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
|
::: $DIR/drop.rs:23:1
|
||||||
|
|
|
|
||||||
LL | };
|
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
|
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.
|
| 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
|
::: $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
|
| 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
|
::: $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
|
| 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
|
::: $DIR/offset_from_ub.rs:31:1
|
||||||
|
|
|
|
||||||
|
|
@ -64,7 +67,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| invalid use of NULL pointer
|
| 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
|
::: $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
|
| 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
|
::: $DIR/offset_from_ub.rs:45:1
|
||||||
|
|
|
|
||||||
|
|
|
||||||
|
|
@ -4,76 +4,140 @@ error[E0080]: evaluation of constant value failed
|
||||||
LL | hint_unreachable()
|
LL | hint_unreachable()
|
||||||
| ------------------
|
| ------------------
|
||||||
| |
|
| |
|
||||||
| 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
|
||||||
...
|
...
|
||||||
LL | fake_type()
|
LL | fake_type()
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| reached the configured maximum number of stack frames
|
| 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
|
error: any use of this value will cause an error
|
||||||
--> $DIR/uninhabited-const-issue-61744.rs:12:36
|
--> $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.
|
// This takes much less time to build than all of Servo and supports stable Rust.
|
||||||
packages: &["selectors"],
|
packages: &["selectors"],
|
||||||
},
|
},
|
||||||
Test {
|
|
||||||
name: "webrender",
|
|
||||||
repo: "https://github.com/servo/webrender",
|
|
||||||
sha: "a3d6e6894c5a601fa547c6273eb963ca1321c2bb",
|
|
||||||
lock: None,
|
|
||||||
packages: &[],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
fn main() {
|
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) {
|
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);
|
let diff_results = make_diff(expected, actual, context_size);
|
||||||
for result in diff_results {
|
for result in diff_results {
|
||||||
let mut line_number = result.line_number;
|
let mut line_number = result.line_number;
|
||||||
for line in result.lines {
|
for line in result.lines {
|
||||||
match line {
|
match line {
|
||||||
DiffLine::Expected(e) => {
|
DiffLine::Expected(e) => {
|
||||||
writeln!(dest, "-\t{}", e).unwrap();
|
println!("-\t{}", e);
|
||||||
line_number += 1;
|
line_number += 1;
|
||||||
}
|
}
|
||||||
DiffLine::Context(c) => {
|
DiffLine::Context(c) => {
|
||||||
writeln!(dest, "{}\t{}", line_number, c).unwrap();
|
println!("{}\t{}", line_number, c);
|
||||||
line_number += 1;
|
line_number += 1;
|
||||||
}
|
}
|
||||||
DiffLine::Resulting(r) => {
|
DiffLine::Resulting(r) => {
|
||||||
writeln!(dest, "+\t{}", r).unwrap();
|
println!("+\t{}", r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeln!(dest).unwrap();
|
println!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue