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:
bors 2020-04-01 20:30:35 +00:00
commit 76b11980ad
36 changed files with 410 additions and 362 deletions

View File

@ -79,7 +79,7 @@ fn uncached_llvm_type<'a, 'tcx>(
};
match layout.fields {
layout::FieldPlacement::Union(_) => {
layout::FieldsShape::Union(_) => {
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
let packed = false;
match name {
@ -91,10 +91,10 @@ fn uncached_llvm_type<'a, 'tcx>(
}
}
}
layout::FieldPlacement::Array { count, .. } => {
layout::FieldsShape::Array { count, .. } => {
cx.type_array(layout.field(cx, 0).llvm_type(cx), count)
}
layout::FieldPlacement::Arbitrary { .. } => match name {
layout::FieldsShape::Arbitrary { .. } => match name {
None => {
let (llfields, packed) = struct_llfields(cx, layout);
cx.type_struct(&llfields, packed)
@ -371,13 +371,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
_ => {}
}
match self.fields {
layout::FieldPlacement::Union(_) => {
layout::FieldsShape::Union(_) => {
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
}
layout::FieldPlacement::Array { .. } => index as u64,
layout::FieldsShape::Array { .. } => index as u64,
layout::FieldPlacement::Arbitrary { .. } => {
layout::FieldsShape::Arbitrary { .. } => {
1 + (self.fields.memory_index(index) as u64) * 2
}
}

View File

@ -66,7 +66,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
}
pub fn len<Cx: ConstMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V {
if let layout::FieldPlacement::Array { count, .. } = self.layout.fields {
if let layout::FieldsShape::Array { count, .. } = self.layout.fields {
if self.layout.is_unsized() {
assert_eq!(count, 0);
self.llextra.unwrap()

View File

@ -1,4 +1,4 @@
A non-root module attempts to import macros from another crate.
A non-root module tried to import macros from another crate.
Example of erroneous code:
@ -17,7 +17,7 @@ Either move the macro import to crate root or do without the foreign macros.
This will work:
```
#[macro_use(debug_assert)]
#[macro_use(debug_assert)] // ok!
extern crate core;
mod foo {

View File

@ -53,9 +53,8 @@ pub struct ConstEvalErr<'tcx> {
#[derive(Debug)]
pub struct FrameInfo<'tcx> {
/// This span is in the caller.
pub call_site: Span,
pub instance: ty::Instance<'tcx>,
pub span: Span,
pub lint_root: Option<hir::HirId>,
}
@ -65,12 +64,12 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
== DefPathData::ClosureExpr
{
write!(f, "inside call to closure")?;
write!(f, "inside closure")?;
} else {
write!(f, "inside call to `{}`", self.instance)?;
write!(f, "inside `{}`", self.instance)?;
}
if !self.call_site.is_dummy() {
let lo = tcx.sess.source_map().lookup_char_pos(self.call_site.lo());
if !self.span.is_dummy() {
let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo());
write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?;
}
Ok(())
@ -168,13 +167,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
if let Some(span_msg) = span_msg {
err.span_label(self.span, span_msg);
}
// Add spans for the stacktrace.
// Skip the last, which is just the environment of the constant. The stacktrace
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
// on constant values.
if !self.stacktrace.is_empty() {
for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] {
err.span_label(frame_info.call_site, frame_info.to_string());
// Add spans for the stacktrace. Don't print a single-line backtrace though.
if self.stacktrace.len() > 1 {
for frame_info in &self.stacktrace {
err.span_label(frame_info.span, frame_info.to_string());
}
}
// Let the caller finish the job.

View File

@ -154,14 +154,44 @@ impl Iterator for Ancestors<'_> {
}
}
pub struct NodeItem<T> {
pub node: Node,
pub item: T,
/// Information about the most specialized definition of an associated item.
pub struct LeafDef {
/// The associated item described by this `LeafDef`.
pub item: ty::AssocItem,
/// The node in the specialization graph containing the definition of `item`.
pub defining_node: Node,
/// The "top-most" (ie. least specialized) specialization graph node that finalized the
/// definition of `item`.
///
/// Example:
///
/// ```
/// trait Tr {
/// fn assoc(&self);
/// }
///
/// impl<T> Tr for T {
/// default fn assoc(&self) {}
/// }
///
/// impl Tr for u8 {}
/// ```
///
/// If we start the leaf definition search at `impl Tr for u8`, that impl will be the
/// `finalizing_node`, while `defining_node` will be the generic impl.
///
/// If the leaf definition search is started at the generic impl, `finalizing_node` will be
/// `None`, since the most specialized impl we found still allows overriding the method
/// (doesn't finalize it).
pub finalizing_node: Option<Node>,
}
impl<T> NodeItem<T> {
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> {
NodeItem { node: self.node, item: f(self.item) }
impl LeafDef {
/// Returns whether this definition is known to not be further specializable.
pub fn is_final(&self) -> bool {
self.finalizing_node.is_some()
}
}
@ -173,18 +203,36 @@ impl<'tcx> Ancestors<'tcx> {
tcx: TyCtxt<'tcx>,
trait_item_name: Ident,
trait_item_kind: ty::AssocKind,
) -> Option<NodeItem<ty::AssocItem>> {
) -> Option<LeafDef> {
let trait_def_id = self.trait_def_id;
let mut finalizing_node = None;
self.find_map(|node| {
node.item(tcx, trait_item_name, trait_item_kind, trait_def_id)
.map(|item| NodeItem { node, item })
if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) {
if finalizing_node.is_none() {
let is_specializable = item.defaultness.is_default()
|| tcx.impl_defaultness(node.def_id()).is_default();
if !is_specializable {
finalizing_node = Some(node);
}
}
Some(LeafDef { item, defining_node: node, finalizing_node })
} else {
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
finalizing_node = Some(node);
None
}
})
}
}
/// Walk up the specialization ancestors of a given impl, starting with that
/// impl itself. Returns `None` if an error was reported while building the
/// specialization graph.
/// impl itself.
///
/// Returns `Err` if an error was reported while building the specialization
/// graph.
pub fn ancestors(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,

View File

@ -230,7 +230,7 @@ enum StructKind {
// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
// This is used to go between `memory_index` (source field order to memory order)
// and `inverse_memory_index` (memory order to source field order).
// See also `FieldPlacement::Arbitrary::memory_index` for more details.
// See also `FieldsShape::Arbitrary::memory_index` for more details.
// FIXME(eddyb) build a better abstraction for permutations, if possible.
fn invert_mapping(map: &[u32]) -> Vec<u32> {
let mut inverse = vec![0; map.len()];
@ -257,7 +257,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Arbitrary {
fields: FieldsShape::Arbitrary {
offsets: vec![Size::ZERO, b_offset],
memory_index: vec![0, 1],
},
@ -443,7 +443,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
};
let pair = self.scalar_pair(a.clone(), b.clone());
let pair_offsets = match pair.fields {
FieldPlacement::Arbitrary { ref offsets, ref memory_index } => {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
offsets
}
@ -471,7 +471,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
Ok(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Arbitrary { offsets, memory_index },
fields: FieldsShape::Arbitrary { offsets, memory_index },
abi,
largest_niche,
align,
@ -520,7 +520,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// The never type.
ty::Never => tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Union(0),
fields: FieldsShape::Union(0),
abi: Abi::Uninhabited,
largest_niche: None,
align: dl.i8_align,
@ -581,7 +581,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array { stride: element.size, count },
fields: FieldsShape::Array { stride: element.size, count },
abi,
largest_niche,
align: element.align,
@ -592,7 +592,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let element = self.layout_of(element)?;
tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array { stride: element.size, count: 0 },
fields: FieldsShape::Array { stride: element.size, count: 0 },
abi: Abi::Aggregate { sized: false },
largest_niche: None,
align: element.align,
@ -601,7 +601,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
ty::Str => tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array { stride: Size::from_bytes(1), count: 0 },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
abi: Abi::Aggregate { sized: false },
largest_niche: None,
align: dl.i8_align,
@ -670,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
tcx.intern_layout(Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Array { stride: element.size, count },
fields: FieldsShape::Array { stride: element.size, count },
abi: Abi::Vector { element: scalar, count },
largest_niche: element.largest_niche.clone(),
size,
@ -746,7 +746,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
return Ok(tcx.intern_layout(Layout {
variants: Variants::Single { index },
fields: FieldPlacement::Union(variants[index].len()),
fields: FieldsShape::Union(variants[index].len()),
abi,
largest_niche: None,
align,
@ -980,7 +980,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
discr_index: 0,
variants: st,
},
fields: FieldPlacement::Arbitrary {
fields: FieldsShape::Arbitrary {
offsets: vec![offset],
memory_index: vec![0],
},
@ -1121,7 +1121,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let new_ity_size = ity.size();
for variant in &mut layout_variants {
match variant.fields {
FieldPlacement::Arbitrary { ref mut offsets, .. } => {
FieldsShape::Arbitrary { ref mut offsets, .. } => {
for i in offsets {
if *i <= old_ity_size {
assert_eq!(*i, old_ity_size);
@ -1151,7 +1151,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let mut common_prim = None;
for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
let offsets = match layout_variant.fields {
FieldPlacement::Arbitrary { ref offsets, .. } => offsets,
FieldsShape::Arbitrary { ref offsets, .. } => offsets,
_ => bug!(),
};
let mut fields =
@ -1187,7 +1187,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
if let Some((prim, offset)) = common_prim {
let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
let pair_offsets = match pair.fields {
FieldPlacement::Arbitrary { ref offsets, ref memory_index } => {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
offsets
}
@ -1218,7 +1218,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
discr_index: 0,
variants: layout_variants,
},
fields: FieldPlacement::Arbitrary {
fields: FieldsShape::Arbitrary {
offsets: vec![Size::ZERO],
memory_index: vec![0],
},
@ -1435,7 +1435,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// GeneratorLayout.
debug!("prefix = {:#?}", prefix);
let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
FieldPlacement::Arbitrary { mut offsets, memory_index } => {
FieldsShape::Arbitrary { mut offsets, memory_index } => {
let mut inverse_memory_index = invert_mapping(&memory_index);
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
@ -1458,7 +1458,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let memory_index_b = invert_mapping(&inverse_memory_index_b);
let outer_fields =
FieldPlacement::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
(outer_fields, offsets_b, memory_index_b)
}
_ => bug!(),
@ -1492,7 +1492,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
variant.variants = Variants::Single { index };
let (offsets, memory_index) = match variant.fields {
FieldPlacement::Arbitrary { offsets, memory_index } => (offsets, memory_index),
FieldsShape::Arbitrary { offsets, memory_index } => (offsets, memory_index),
_ => bug!(),
};
@ -1535,7 +1535,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
variant.fields = FieldPlacement::Arbitrary {
variant.fields = FieldsShape::Arbitrary {
offsets: combined_offsets,
memory_index: combined_memory_index,
};
@ -1990,7 +1990,7 @@ where
if index == variant_index &&
// Don't confuse variants of uninhabited enums with the enum itself.
// For more details see https://github.com/rust-lang/rust/issues/69763.
this.fields != FieldPlacement::Union(0) =>
this.fields != FieldsShape::Union(0) =>
{
this.layout
}
@ -2008,7 +2008,7 @@ where
let tcx = cx.tcx();
tcx.intern_layout(Layout {
variants: Variants::Single { index: variant_index },
fields: FieldPlacement::Union(fields),
fields: FieldsShape::Union(fields),
abi: Abi::Uninhabited,
largest_niche: None,
align: tcx.data_layout.i8_align,
@ -2054,7 +2054,7 @@ where
// Reuse the fat `*T` type as its own thin pointer data field.
// This provides information about, e.g., DST struct pointees
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldPlacement` is checked by users.
// as the `Abi` or `FieldsShape` is checked by users.
if i == 0 {
let nil = tcx.mk_unit();
let ptr_ty = if this.ty.is_unsafe_ptr() {
@ -2219,7 +2219,7 @@ where
if let Some(variant) = data_variant {
// We're not interested in any unions.
if let FieldPlacement::Union(_) = variant.fields {
if let FieldsShape::Union(_) = variant.fields {
data_variant = None;
}
}

View File

@ -55,6 +55,6 @@ pub fn error_to_const_error<'mir, 'tcx, M: Machine<'mir, 'tcx>>(
mut error: InterpErrorInfo<'tcx>,
) -> ConstEvalErr<'tcx> {
error.print_backtrace();
let stacktrace = ecx.generate_stacktrace(None);
let stacktrace = ecx.generate_stacktrace();
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
}

View File

@ -46,7 +46,6 @@ fn eval_body_using_ecx<'mir, 'tcx>(
ecx.push_stack_frame(
cid.instance,
body.span,
body,
Some(ret.into()),
StackPopCleanup::None { cleanup: false },

View File

@ -8,9 +8,9 @@ use std::hash::Hash;
use rustc_data_structures::fx::FxHashMap;
use rustc_ast::ast::Mutability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::AssertMessage;
use rustc_span::symbol::Symbol;
use rustc_span::{def_id::DefId, Span};
use crate::interpret::{
self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
@ -64,7 +64,6 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> {
/// If this returns successfully (`Ok`), the function should just be evaluated normally.
fn hook_panic_fn(
&mut self,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
) -> InterpResult<'tcx> {
@ -77,7 +76,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> {
let msg_place = self.deref_operand(args[0])?;
let msg = Symbol::intern(self.read_str(msg_place)?);
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);
Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
} else {
@ -191,7 +190,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
@ -213,7 +211,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
} else {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn!
ecx.hook_panic_fn(span, instance, args)?;
ecx.hook_panic_fn(instance, args)?;
// We certainly do *not* want to actually call the fn
// though, so be sure we return here.
throw_unsup_format!("calling non-const function `{}`", instance)
@ -248,13 +246,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
if ecx.emulate_intrinsic(span, instance, args, ret)? {
if ecx.emulate_intrinsic(instance, args, ret)? {
return Ok(());
}
// An intrinsic that we do not support

View File

@ -17,7 +17,7 @@ use rustc_middle::ty::layout::{self, Align, HasDataLayout, LayoutOf, Size, TyAnd
use rustc_middle::ty::query::TyCtxtAt;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::source_map::{self, Span, DUMMY_SP};
use rustc_span::source_map::DUMMY_SP;
use super::{
Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
@ -57,9 +57,6 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
/// The def_id and substs of the current function.
pub instance: ty::Instance<'tcx>,
/// The span of the call site.
pub span: source_map::Span,
/// Extra data for the machine.
pub extra: Extra,
@ -502,7 +499,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn push_stack_frame(
&mut self,
instance: ty::Instance<'tcx>,
span: Span,
body: &'mir mir::Body<'tcx>,
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
return_to_block: StackPopCleanup,
@ -522,7 +518,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// empty local array, we fill it in below, after we are inside the stack frame and
// all methods actually know about the frame
locals: IndexVec::new(),
span,
instance,
stmt: 0,
extra,
@ -541,7 +536,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// statics and constants don't have `Storage*` statements, no need to look for them
Some(DefKind::Static) | Some(DefKind::Const) | Some(DefKind::AssocConst) => {}
_ => {
trace!("push_stack_frame: {:?}: num_bbs: {}", span, body.basic_blocks().len());
for block in body.basic_blocks() {
for stmt in block.statements.iter() {
use rustc_middle::mir::StatementKind::{StorageDead, StorageLive};
@ -859,33 +853,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
let mut last_span = None;
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
let mut frames = Vec::new();
for frame in self.stack().iter().rev() {
// make sure we don't emit frames that are duplicates of the previous
if explicit_span == Some(frame.span) {
last_span = Some(frame.span);
continue;
}
if let Some(last) = last_span {
if last == frame.span {
continue;
}
} else {
last_span = Some(frame.span);
}
let lint_root = frame.current_source_info().and_then(|source_info| {
let source_info = frame.current_source_info();
let lint_root = source_info.and_then(|source_info| {
match &frame.body.source_scopes[source_info.scope].local_data {
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
mir::ClearCrossCrate::Clear => None,
}
});
let span = source_info.map_or(DUMMY_SP, |source_info| source_info.span);
frames.push(FrameInfo { call_site: frame.span, instance: frame.instance, lint_root });
frames.push(FrameInfo { span, instance: frame.instance, lint_root });
}
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
trace!("generate stacktrace: {:#?}", frames);
frames
}
}
@ -899,7 +881,6 @@ where
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
self.body.hash_stable(hcx, hasher);
self.instance.hash_stable(hcx, hasher);
self.span.hash_stable(hcx, hasher);
self.return_to_block.hash_stable(hcx, hasher);
self.return_place.as_ref().map(|r| &**r).hash_stable(hcx, hasher);
self.locals.hash_stable(hcx, hasher);

View File

@ -15,7 +15,6 @@ use rustc_middle::ty::layout::{LayoutOf, Primitive, Size};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use super::{ImmTy, InterpCx, Machine, OpTy, PlaceTy};
@ -78,7 +77,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Returns `true` if emulation happened.
pub fn emulate_intrinsic(
&mut self,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, M::PointerTag>],
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
@ -101,7 +99,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// `src/librustc_middle/ty/constness.rs`
match intrinsic_name {
sym::caller_location => {
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
let span = self.find_closest_untracked_caller_location();
let location = self.alloc_caller_location_for_span(span);
self.write_scalar(location.ptr, dest)?;
}
@ -118,7 +116,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::needs_drop => self.tcx.types.bool,
sym::type_id => self.tcx.types.u64,
sym::type_name => self.tcx.mk_static_str(),
_ => span_bug!(span, "Already checked for nullary intrinsics"),
_ => bug!("already checked for nullary intrinsics"),
};
let val = self.const_eval(gid, ty)?;
self.copy_op(val, dest)?;

View File

@ -12,18 +12,21 @@ use crate::interpret::{
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
/// `None` is returned and the callsite of the function invocation itself should be used.
crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
let mut caller_span = None;
for next_caller in self.stack.iter().rev() {
if !next_caller.instance.def.requires_caller_location(*self.tcx) {
return caller_span;
}
caller_span = Some(next_caller.span);
}
caller_span
/// frame which is not `#[track_caller]`.
crate fn find_closest_untracked_caller_location(&self) -> Span {
self.stack
.iter()
.rev()
// Find first non-`#[track_caller]` frame.
.find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
// Assert that there is always such a frame.
.unwrap()
.current_source_info()
// Assert that the frame we look at is actually executing code currently
// (`current_source_info` is None when we are unwinding and the frame does
// not require cleanup).
.unwrap()
.span
}
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.

View File

@ -7,7 +7,7 @@ use std::hash::Hash;
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty};
use rustc_span::{def_id::DefId, Span};
use rustc_span::def_id::DefId;
use super::{
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
@ -135,7 +135,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
/// was used.
fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
@ -156,7 +155,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
/// responsibility to advance the instruction pointer as appropriate.
fn call_intrinsic(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,

View File

@ -219,7 +219,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
// Go through the layout. There are lots of types that support a length,
// e.g., SIMD types.
match self.layout.fields {
layout::FieldPlacement::Array { count, .. } => Ok(count),
layout::FieldsShape::Array { count, .. } => Ok(count),
_ => bug!("len not supported on sized type {:?}", self.layout.ty),
}
}
@ -437,7 +437,7 @@ where
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
// Not using the layout method because we want to compute on u64
match base.layout.fields {
layout::FieldPlacement::Array { stride, .. } => {
layout::FieldsShape::Array { stride, .. } => {
let len = base.len(self)?;
if index >= len {
// This can only be reached in ConstProp and non-rustc-MIR.
@ -463,7 +463,7 @@ where
{
let len = base.len(self)?; // also asserts that we have a type where this makes sense
let stride = match base.layout.fields {
layout::FieldPlacement::Array { stride, .. } => stride,
layout::FieldsShape::Array { stride, .. } => stride,
_ => bug!("mplace_array_fields: expected an array layout"),
};
let layout = base.layout.field(self, 0)?;
@ -493,7 +493,7 @@ where
// Not using layout method because that works with usize, and does not work with slices
// (that have count 0 in their layout).
let from_offset = match base.layout.fields {
layout::FieldPlacement::Array { stride, .. } => stride * from, // `Size` multiplication is checked
layout::FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
_ => bug!("Unexpected layout of index access: {:#?}", base.layout),
};

View File

@ -4,7 +4,6 @@ use std::convert::TryFrom;
use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
use rustc_middle::ty::Instance;
use rustc_middle::{mir, ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use super::{
@ -71,14 +70,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Some((dest, ret)) => Some((self.eval_place(dest)?, ret)),
None => None,
};
self.eval_fn_call(
fn_val,
terminator.source_info.span,
abi,
&args[..],
ret,
*cleanup,
)?;
self.eval_fn_call(fn_val, abi, &args[..], ret, *cleanup)?;
}
Drop { location, target, unwind } => {
@ -88,7 +80,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
self.drop_in_place(place, instance, terminator.source_info.span, target, unwind)?;
self.drop_in_place(place, instance, target, unwind)?;
}
Assert { ref cond, expected, ref msg, target, cleanup } => {
@ -196,7 +188,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn eval_fn_call(
&mut self,
fn_val: FnVal<'tcx, M::ExtraFnVal>,
span: Span,
caller_abi: Abi,
args: &[OpTy<'tcx, M::PointerTag>],
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
@ -242,7 +233,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match instance.def {
ty::InstanceDef::Intrinsic(..) => {
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
M::call_intrinsic(self, span, instance, args, ret, unwind)
M::call_intrinsic(self, instance, args, ret, unwind)
}
ty::InstanceDef::VtableShim(..)
| ty::InstanceDef::ReifyShim(..)
@ -252,14 +243,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
| ty::InstanceDef::CloneShim(..)
| ty::InstanceDef::Item(_) => {
// We need MIR for this fn
let body = match M::find_mir_or_eval_fn(self, span, instance, args, ret, unwind)? {
let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
Some(body) => body,
None => return Ok(()),
};
self.push_stack_frame(
instance,
span,
body,
ret.map(|p| p.0),
StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind },
@ -407,7 +397,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
OpTy::from(ImmTy { layout: this_receiver_ptr, imm: receiver_place.ptr.into() });
trace!("Patched self operand to {:#?}", args[0]);
// recurse with concrete function
self.eval_fn_call(drop_fn, span, caller_abi, &args, ret, unwind)
self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind)
}
}
}
@ -416,7 +406,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&mut self,
place: PlaceTy<'tcx, M::PointerTag>,
instance: ty::Instance<'tcx>,
span: Span,
target: mir::BasicBlock,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
@ -444,7 +433,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.eval_fn_call(
FnVal::Instance(instance),
span,
Abi::Rust,
&[arg.into()],
Some((dest.into(), target)),

View File

@ -207,10 +207,10 @@ macro_rules! make_value_visitor {
// Visit the fields of this value.
match v.layout().fields {
layout::FieldPlacement::Union(fields) => {
layout::FieldsShape::Union(fields) => {
self.visit_union(v, fields)?;
},
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
layout::FieldsShape::Arbitrary { ref offsets, .. } => {
// FIXME: We collect in a vec because otherwise there are lifetime
// errors: Projecting to a field needs access to `ecx`.
let fields: Vec<InterpResult<'tcx, Self::V>> =
@ -220,7 +220,7 @@ macro_rules! make_value_visitor {
.collect();
self.visit_aggregate(v, fields.into_iter())?;
},
layout::FieldPlacement::Array { .. } => {
layout::FieldsShape::Array { .. } => {
// Let's get an mplace first.
let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx());
// Now we can go over all the fields.

View File

@ -183,7 +183,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_span: Span,
_instance: ty::Instance<'tcx>,
_args: &[OpTy<'tcx>],
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
@ -204,7 +203,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
fn call_intrinsic(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_span: Span,
_instance: ty::Instance<'tcx>,
_args: &[OpTy<'tcx>],
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
@ -361,7 +359,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
ecx.push_stack_frame(
Instance::new(def_id, substs),
span,
dummy_body,
ret.map(Into::into),
StackPopCleanup::None { cleanup: false },

View File

@ -49,7 +49,7 @@ where
// use of float registers to structures (not unions) containing exactly one or two
// float fields.
if let abi::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
if let abi::FieldsShape::Arbitrary { .. } = ret.layout.fields {
if ret.layout.fields.count() == 1 {
if let Some(reg) = float_reg(cx, ret, 0) {
ret.cast_to(reg);
@ -88,15 +88,15 @@ where
let mut prefix_index = 0;
match arg.layout.fields {
abi::FieldPlacement::Array { .. } => {
abi::FieldsShape::Array { .. } => {
// Arrays are passed indirectly
arg.make_indirect();
return;
}
abi::FieldPlacement::Union(_) => {
abi::FieldsShape::Union(_) => {
// Unions and are always treated as a series of 64-bit integer chunks
}
abi::FieldPlacement::Arbitrary { .. } => {
abi::FieldsShape::Arbitrary { .. } => {
// Structures are split up into a series of 64-bit integer chunks, but any aligned
// doubles not part of another aggregate are passed as floats.
let mut last_offset = Size::ZERO;

View File

@ -1,4 +1,4 @@
use crate::abi::{self, Abi, Align, FieldPlacement, Size};
use crate::abi::{self, Abi, Align, FieldsShape, Size};
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
use crate::spec::{self, HasTargetSpec};
@ -315,7 +315,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
start: Size|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
let is_union = match layout.fields {
FieldPlacement::Array { count, .. } => {
FieldsShape::Array { count, .. } => {
assert_eq!(start, Size::ZERO);
let result = if count > 0 {
@ -325,8 +325,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
};
return Ok((result, layout.size));
}
FieldPlacement::Union(_) => true,
FieldPlacement::Arbitrary { .. } => false,
FieldsShape::Union(_) => true,
FieldsShape::Arbitrary { .. } => false,
};
let mut result = HomogeneousAggregate::NoData;

View File

@ -6,7 +6,7 @@
use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
use crate::abi::{
self, Abi, FieldPlacement, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
};
use crate::spec::HasTargetSpec;
@ -87,12 +87,12 @@ where
},
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
FieldPlacement::Union(_) => {
FieldsShape::Union(_) => {
if !arg_layout.is_zst() {
return Err(CannotUseFpConv);
}
}
FieldPlacement::Array { count, .. } => {
FieldsShape::Array { count, .. } => {
for _ in 0..count {
let elem_layout = arg_layout.field(cx, 0);
should_use_fp_conv_helper(
@ -105,7 +105,7 @@ where
)?;
}
}
FieldPlacement::Arbitrary { .. } => {
FieldsShape::Arbitrary { .. } => {
match arg_layout.variants {
abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
abi::Variants::Single { .. } => (),

View File

@ -618,7 +618,7 @@ impl Scalar {
/// Describes how the fields of a type are located in memory.
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum FieldPlacement {
pub enum FieldsShape {
/// All fields start at no offset. The `usize` is the field count.
///
/// In the case of primitives the number of fields is `0`.
@ -657,38 +657,38 @@ pub enum FieldPlacement {
},
}
impl FieldPlacement {
impl FieldsShape {
pub fn count(&self) -> usize {
match *self {
FieldPlacement::Union(count) => count,
FieldPlacement::Array { count, .. } => {
FieldsShape::Union(count) => count,
FieldsShape::Array { count, .. } => {
let usize_count = count as usize;
assert_eq!(usize_count as u64, count);
usize_count
}
FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len(),
FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
}
}
pub fn offset(&self, i: usize) -> Size {
match *self {
FieldPlacement::Union(count) => {
FieldsShape::Union(count) => {
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
Size::ZERO
}
FieldPlacement::Array { stride, count } => {
FieldsShape::Array { stride, count } => {
let i = u64::try_from(i).unwrap();
assert!(i < count);
stride * i
}
FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i],
FieldsShape::Arbitrary { ref offsets, .. } => offsets[i],
}
}
pub fn memory_index(&self, i: usize) -> usize {
match *self {
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
FieldPlacement::Arbitrary { ref memory_index, .. } => {
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
FieldsShape::Arbitrary { ref memory_index, .. } => {
let r = memory_index[i];
assert_eq!(r as usize as u32, r);
r as usize
@ -704,7 +704,7 @@ impl FieldPlacement {
let use_small = self.count() <= inverse_small.len();
// We have to write this logic twice in order to keep the array small.
if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
if let FieldsShape::Arbitrary { ref memory_index, .. } = *self {
if use_small {
for i in 0..self.count() {
inverse_small[memory_index[i] as usize] = i as u8;
@ -718,8 +718,8 @@ impl FieldPlacement {
}
(0..self.count()).map(move |i| match *self {
FieldPlacement::Union(_) | FieldPlacement::Array { .. } => i,
FieldPlacement::Arbitrary { .. } => {
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
FieldsShape::Arbitrary { .. } => {
if use_small {
inverse_small[i] as usize
} else {
@ -888,7 +888,7 @@ impl Niche {
pub struct Layout {
/// Says where the fields are located within the layout.
/// Primitives and uninhabited enums appear as unions without fields.
pub fields: FieldPlacement,
pub fields: FieldsShape,
/// Encodes information about multi-variant layouts.
/// Even with `Multiple` variants, a layout still has its own fields! Those are then
@ -923,7 +923,7 @@ impl Layout {
let align = scalar.value.align(cx);
Layout {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Union(0),
fields: FieldsShape::Union(0),
abi: Abi::Scalar(scalar),
largest_niche,
size,

View File

@ -54,7 +54,6 @@ pub use self::project::{
};
pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
pub use self::specialize::find_associated_item;
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
@ -64,8 +63,7 @@ pub use self::structural_match::NonStructuralMatchTy;
pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
pub use self::util::{
get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
predicate_for_trait_def, upcast_choices,
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
};
pub use self::util::{
supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,

View File

@ -1015,49 +1015,21 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
.map_err(|ErrorReported| ())?;
let is_default = if node_item.node.is_from_trait() {
// If true, the impl inherited a `type Foo = Bar`
// given in the trait, which is implicitly default.
// Otherwise, the impl did not specify `type` and
// neither did the trait:
//
// ```rust
// trait Foo { type T; }
// impl Foo for Bar { }
// ```
//
// This is an error, but it will be
// reported in `check_impl_items_against_trait`.
// We accept it here but will flag it as
// an error when we confirm the candidate
// (which will ultimately lead to `normalize_to_error`
// being invoked).
false
if node_item.is_final() {
// Non-specializable items are always projectable.
true
} else {
// If we're looking at a trait *impl*, the item is
// specializable if the impl or the item are marked
// `default`.
node_item.item.defaultness.is_default()
|| super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
};
match is_default {
// Non-specializable items are always projectable
false => true,
// Only reveal a specializable default if we're past type-checking
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
true if obligation.param_env.reveal == Reveal::All => {
if obligation.param_env.reveal == Reveal::All {
// NOTE(eddyb) inference variables can resolve to parameters, so
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
let poly_trait_ref =
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
!poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
}
true => {
} else {
debug!(
"assemble_candidates_from_impls: not eligible due to default: \
assoc_ty={} predicate={}",
@ -1422,7 +1394,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
return Progress { ty: tcx.types.err, obligations: nested };
}
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
let substs =
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
@ -1447,7 +1420,7 @@ fn assoc_ty_def(
selcx: &SelectionContext<'_, '_>,
impl_def_id: DefId,
assoc_ty_def_id: DefId,
) -> Result<specialization_graph::NodeItem<ty::AssocItem>, ErrorReported> {
) -> Result<specialization_graph::LeafDef, ErrorReported> {
let tcx = selcx.tcx();
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
@ -1464,9 +1437,10 @@ fn assoc_ty_def(
if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
{
return Ok(specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
return Ok(specialization_graph::LeafDef {
item: *item,
defining_node: impl_node,
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
});
}
}

View File

@ -20,7 +20,7 @@ use rustc_errors::struct_span_err;
use rustc_hir::def_id::DefId;
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::DUMMY_SP;
@ -112,48 +112,6 @@ pub fn translate_substs<'a, 'tcx>(
source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
}
/// Given a selected impl described by `impl_data`, returns the
/// definition and substitutions for the method with the name `name`
/// the kind `kind`, and trait method substitutions `substs`, in
/// that impl, a less specialized impl, or the trait default,
/// whichever applies.
pub fn find_associated_item<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
item: &ty::AssocItem,
substs: SubstsRef<'tcx>,
impl_data: &super::VtableImplData<'tcx, ()>,
) -> (DefId, SubstsRef<'tcx>) {
debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
assert!(!substs.needs_infer());
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_def_id);
if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) {
match ancestors.leaf_def(tcx, item.ident, item.kind) {
Some(node_item) => {
let substs = tcx.infer_ctxt().enter(|infcx| {
let param_env = param_env.with_reveal_all();
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
let substs = translate_substs(
&infcx,
param_env,
impl_data.impl_def_id,
substs,
node_item.node,
);
infcx.tcx.erase_regions(&substs)
});
(node_item.item.def_id, substs)
}
None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
}
} else {
(item.def_id, substs)
}
}
/// Is `impl1` a specialization of `impl2`?
///
/// Specialization is determined by the sets of types to which the impls apply;

View File

@ -4,7 +4,6 @@ use smallvec::smallvec;
use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
@ -651,22 +650,8 @@ pub fn generator_trait_ref_and_outputs(
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
}
pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
match tcx.hir().as_local_hir_id(node_item_def_id) {
Some(hir_id) => {
let item = tcx.hir().expect_item(hir_id);
if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
defaultness.is_default()
} else {
false
}
}
None => tcx.impl_defaultness(node_item_def_id).is_default(),
}
}
pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final()
}
pub enum TupleArgumentsFlag {

View File

@ -1,9 +1,11 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
use rustc_span::sym;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal};
use log::debug;
@ -82,21 +84,50 @@ fn resolve_associated_item<'tcx>(
// the actual function:
match vtbl {
traits::VtableImpl(impl_data) => {
let (def_id, substs) =
traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
debug!(
"resolving VtableImpl: {:?}, {:?}, {:?}, {:?}",
param_env, trait_item, rcvr_substs, impl_data
);
assert!(!rcvr_substs.needs_infer());
assert!(!trait_ref.needs_infer());
let resolved_item = tcx.associated_item(def_id);
let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
let trait_def = tcx.trait_def(trait_def_id);
let leaf_def = trait_def
.ancestors(tcx, impl_data.impl_def_id)
.ok()?
.leaf_def(tcx, trait_item.ident, trait_item.kind)
.unwrap_or_else(|| {
bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id);
});
let def_id = leaf_def.item.def_id;
let substs = tcx.infer_ctxt().enter(|infcx| {
let param_env = param_env.with_reveal_all();
let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
let substs = translate_substs(
&infcx,
param_env,
impl_data.impl_def_id,
substs,
leaf_def.defining_node,
);
infcx.tcx.erase_regions(&substs)
});
// Since this is a trait item, we need to see if the item is either a trait default item
// or a specialization because we can't resolve those unless we can `Reveal::All`.
// NOTE: This should be kept in sync with the similar code in
// `rustc_middle::traits::project::assemble_candidates_from_impls()`.
let eligible = if !resolved_item.defaultness.is_default() {
let eligible = if leaf_def.is_final() {
// Non-specializable items are always projectable.
true
} else if param_env.reveal == traits::Reveal::All {
!trait_ref.needs_subst()
} else {
false
// Only reveal a specializable default if we're past type-checking
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
if param_env.reveal == Reveal::All { !trait_ref.needs_subst() } else { false }
};
if !eligible {

View File

@ -165,6 +165,16 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
)
}
fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
let item = tcx.hir().expect_item(hir_id);
if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
defaultness
} else {
bug!("`impl_defaultness` called on {:?}", item);
}
}
/// Calculates the `Sized` constraint.
///
/// In fact, there are only a few options for the types in the constraint:
@ -371,6 +381,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
crate_hash,
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
..*providers
};
}

View File

@ -1942,7 +1942,7 @@ fn check_specialization_validity<'tcx>(
// grandparent. In that case, if parent is a `default impl`, inherited items use the
// "defaultness" from the grandparent, else they are final.
None => {
if traits::impl_is_default(tcx, parent_impl.def_id()) {
if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
None
} else {
Some(Err(parent_impl.def_id()))
@ -2114,10 +2114,10 @@ fn check_impl_items_against_trait<'tcx>(
for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
let is_implemented = ancestors
.leaf_def(tcx, trait_item.ident, trait_item.kind)
.map(|node_item| !node_item.node.is_from_trait())
.map(|node_item| !node_item.defining_node.is_from_trait())
.unwrap_or(false);
if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
if !trait_item.defaultness.has_value() {
missing_items.push(*trait_item);
}

View File

@ -5,7 +5,8 @@ LL | unsafe { std::mem::transmute(()) }
| ^^^^^^^^^^^^^^^^^^^^^^^
| |
| transmuting to uninhabited type
| inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
| inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
...
LL | const FOO: [Empty; 3] = [foo(); 3];
| -----------------------------------

View File

@ -17,7 +17,8 @@ LL | my_fn();
| ^^^^^^^
| |
| calling a function with ABI C using caller ABI Rust
| inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17
| inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
| inside `VAL` at $DIR/abi-mismatch.rs:13:17
...
LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
| --------------------------------------------------------------------------------------

View File

@ -12,12 +12,15 @@ LL | | // Code here does not matter - this is replaced by the
LL | | // real drop glue by the compiler.
LL | | drop_in_place(to_drop)
LL | | }
| |_^ calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
| | ^
| | |
| |_calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
| inside `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $SRC_DIR/libcore/ptr/mod.rs:LL:COL
|
::: $DIR/drop.rs:23:1
|
LL | };
| - inside call to `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
| - inside `TEST_BAD` at $DIR/drop.rs:23:1
error: aborting due to previous error

View File

@ -5,7 +5,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| ptr_offset_from cannot compute offset of pointers into different allocations.
| inside call to `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $DIR/offset_from_ub.rs:22:27
| inside `std::ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
| inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:22:27
|
::: $DIR/offset_from_ub.rs:16:1
|
@ -27,7 +28,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unable to turn bytes into a pointer
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:28:14
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
| inside `NOT_PTR` at $DIR/offset_from_ub.rs:28:14
|
::: $DIR/offset_from_ub.rs:26:1
|
@ -44,7 +46,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| exact_div: 1isize cannot be divided by 2isize without remainder
| inside call to `std::ptr::const_ptr::<impl *const u16>::offset_from` at $DIR/offset_from_ub.rs:36:14
| inside `std::ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
| inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:36:14
|
::: $DIR/offset_from_ub.rs:31:1
|
@ -64,7 +67,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| invalid use of NULL pointer
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:42:14
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
| inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:42:14
|
::: $DIR/offset_from_ub.rs:39:1
|
@ -82,7 +86,8 @@ LL | intrinsics::ptr_offset_from(self, origin)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unable to turn bytes into a pointer
| inside call to `std::ptr::const_ptr::<impl *const u8>::offset_from` at $DIR/offset_from_ub.rs:49:14
| inside `std::ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
| inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:49:14
|
::: $DIR/offset_from_ub.rs:45:1
|

View File

@ -4,76 +4,140 @@ error[E0080]: evaluation of constant value failed
LL | hint_unreachable()
| ------------------
| |
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside call to `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
...
LL | fake_type()
| ^^^^^^^^^^^
| |
| reached the configured maximum number of stack frames
| inside call to `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
error: any use of this value will cause an error
--> $DIR/uninhabited-const-issue-61744.rs:12:36

View 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
}

View File

@ -58,13 +58,6 @@ const TEST_REPOS: &'static [Test] = &[
// This takes much less time to build than all of Servo and supports stable Rust.
packages: &["selectors"],
},
Test {
name: "webrender",
repo: "https://github.com/servo/webrender",
sha: "a3d6e6894c5a601fa547c6273eb963ca1321c2bb",
lock: None,
packages: &[],
},
];
fn main() {

View File

@ -180,29 +180,25 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
}
fn print_diff(expected: &str, actual: &str, context_size: usize) {
write_diff(expected, actual, context_size, std::io::stdout());
}
fn write_diff(expected: &str, actual: &str, context_size: usize, mut dest: impl io::Write) {
let diff_results = make_diff(expected, actual, context_size);
for result in diff_results {
let mut line_number = result.line_number;
for line in result.lines {
match line {
DiffLine::Expected(e) => {
writeln!(dest, "-\t{}", e).unwrap();
println!("-\t{}", e);
line_number += 1;
}
DiffLine::Context(c) => {
writeln!(dest, "{}\t{}", line_number, c).unwrap();
println!("{}\t{}", line_number, c);
line_number += 1;
}
DiffLine::Resulting(r) => {
writeln!(dest, "+\t{}", r).unwrap();
println!("+\t{}", r);
}
}
}
writeln!(dest).unwrap();
println!();
}
}