Auto merge of #98910 - Dylan-DPC:rollup-9x82wdg, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #97300 (Implement `FusedIterator` for `std::net::[Into]Incoming`)
 - #98761 (more `need_type_info` improvements)
 - #98811 (Interpret: AllocRange Debug impl, and use it more consistently)
 - #98847 (fix interpreter validity check on Box)
 - #98854 (clean up the borrowing in rustc_hir_pretty)
 - #98873 (Suggest `#[derive(Default)]` to enums with `#[default]`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2022-07-05 06:44:49 +00:00
31 changed files with 574 additions and 446 deletions
@@ -276,7 +276,7 @@ pub fn deallocate_ptr(
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx> {
let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?;
trace!("deallocating: {}", alloc_id);
trace!("deallocating: {alloc_id:?}");
if offset.bytes() != 0 {
throw_ub_format!(
@@ -289,10 +289,10 @@ pub fn deallocate_ptr(
// Deallocating global memory -- always an error
return Err(match self.tcx.get_global_alloc(alloc_id) {
Some(GlobalAlloc::Function(..)) => {
err_ub_format!("deallocating {}, which is a function", alloc_id)
err_ub_format!("deallocating {alloc_id:?}, which is a function")
}
Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
err_ub_format!("deallocating {}, which is static memory", alloc_id)
err_ub_format!("deallocating {alloc_id:?}, which is static memory")
}
None => err_ub!(PointerUseAfterFree(alloc_id)),
}
@@ -302,21 +302,17 @@ pub fn deallocate_ptr(
debug!(?alloc);
if alloc.mutability == Mutability::Not {
throw_ub_format!("deallocating immutable allocation {}", alloc_id);
throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
}
if alloc_kind != kind {
throw_ub_format!(
"deallocating {}, which is {} memory, using {} deallocation operation",
alloc_id,
alloc_kind,
kind
"deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation"
);
}
if let Some((size, align)) = old_size_and_align {
if size != alloc.size() || align != alloc.align {
throw_ub_format!(
"incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}",
alloc_id,
"incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}",
alloc.size().bytes(),
alloc.align.bytes(),
size.bytes(),
@@ -815,7 +811,7 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>(
continue;
}
write!(fmt, "{}", id)?;
write!(fmt, "{id:?}")?;
match self.ecx.memory.alloc_map.get(id) {
Some(&(kind, ref alloc)) => {
// normal alloc
@@ -859,25 +855,21 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>(
/// Reading and writing.
impl<'tcx, 'a, Tag: Provenance, Extra> AllocRefMut<'a, 'tcx, Tag, Extra> {
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn write_scalar(
&mut self,
range: AllocRange,
val: ScalarMaybeUninit<Tag>,
) -> InterpResult<'tcx> {
let range = self.range.subrange(range);
debug!(
"write_scalar in {} at {:#x}, size {}: {:?}",
self.alloc_id,
range.start.bytes(),
range.size.bytes(),
val
);
debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id);
Ok(self
.alloc
.write_scalar(&self.tcx, range, val)
.map_err(|e| e.to_interp_error(self.alloc_id))?)
}
/// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn write_ptr_sized(
&mut self,
offset: Size,
@@ -896,6 +888,7 @@ pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
}
impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn read_scalar(
&self,
range: AllocRange,
@@ -906,24 +899,16 @@ pub fn read_scalar(
.alloc
.read_scalar(&self.tcx, range, read_provenance)
.map_err(|e| e.to_interp_error(self.alloc_id))?;
debug!(
"read_scalar in {} at {:#x}, size {}: {:?}",
self.alloc_id,
range.start.bytes(),
range.size.bytes(),
res
);
debug!("read_scalar at {:?}{range:?}: {res:?}", self.alloc_id);
Ok(res)
}
pub fn read_integer(
&self,
offset: Size,
size: Size,
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
self.read_scalar(alloc_range(offset, size), /*read_provenance*/ false)
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
self.read_scalar(range, /*read_provenance*/ false)
}
/// `offset` is relative to this allocation reference, not the base of the allocation.
pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
self.read_scalar(
alloc_range(offset, self.tcx.data_layout().pointer_size),
@@ -931,6 +916,7 @@ pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit
)
}
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn check_bytes(
&self,
range: AllocRange,
@@ -1,6 +1,6 @@
use std::convert::TryFrom;
use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic};
use rustc_middle::mir::interpret::{alloc_range, InterpResult, Pointer, PointerArithmetic};
use rustc_middle::ty::{
self, Ty, TyCtxt, COMMON_VTABLE_ENTRIES_ALIGN, COMMON_VTABLE_ENTRIES_DROPINPLACE,
COMMON_VTABLE_ENTRIES_SIZE,
@@ -102,18 +102,18 @@ pub fn read_size_and_align_from_vtable(
)?
.expect("cannot be a ZST");
let size = vtable
.read_integer(
.read_integer(alloc_range(
pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap(),
pointer_size,
)?
))?
.check_init()?;
let size = size.to_machine_usize(self)?;
let size = Size::from_bytes(size);
let align = vtable
.read_integer(
.read_integer(alloc_range(
pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap(),
pointer_size,
)?
))?
.check_init()?;
let align = align.to_machine_usize(self)?;
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
@@ -593,16 +593,6 @@ fn try_visit_primitive(
self.check_safe_pointer(value, "reference")?;
Ok(true)
}
ty::Adt(def, ..) if def.is_box() => {
let unique = self.ecx.operand_field(value, 0)?;
let nonnull = self.ecx.operand_field(&unique, 0)?;
let ptr = self.ecx.operand_field(&nonnull, 0)?;
self.check_safe_pointer(&ptr, "box")?;
// Check other fields of Box
self.walk_value(value)?;
Ok(true)
}
ty::FnPtr(_sig) => {
let value = try_validation!(
self.ecx.read_scalar(value).and_then(|v| v.check_init()),
@@ -813,6 +803,12 @@ fn visit_union(
Ok(())
}
#[inline]
fn visit_box(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
self.check_safe_pointer(op, "box")?;
Ok(())
}
#[inline]
fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
trace!("visit_value: {:?}, {:?}", *op, op.layout);
@@ -821,8 +817,6 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx>
if self.try_visit_primitive(op)? {
return Ok(());
}
// Sanity check: `builtin_deref` does not know any pointers that are not primitive.
assert!(op.layout.ty.builtin_deref(true).is_none());
// Special check preventing `UnsafeCell` in the inner part of constants
if let Some(def) = op.layout.ty.ty_adt_def() {
@@ -151,6 +151,14 @@ fn visit_union(&mut self, _v: &Self::V, _fields: NonZeroUsize) -> InterpResult<'
{
Ok(())
}
/// Visits the given value as the pointer of a `Box`. There is nothing to recurse into.
/// The type of `v` will be a raw pointer, but this is a field of `Box<T>` and the
/// pointee type is the actual `T`.
#[inline(always)]
fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx>
{
Ok(())
}
/// Visits this value as an aggregate, you are getting an iterator yielding
/// all the fields (still in an `InterpResult`, you have to do error handling yourself).
/// Recurses into the fields.
@@ -221,6 +229,47 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx>
// Slices do not need special handling here: they have `Array` field
// placement with length 0, so we enter the `Array` case below which
// indirectly uses the metadata to determine the actual length.
// However, `Box`... let's talk about `Box`.
ty::Adt(def, ..) if def.is_box() => {
// `Box` is a hybrid primitive-library-defined type that one the one hand is
// a dereferenceable pointer, on the other hand has *basically arbitrary
// user-defined layout* since the user controls the 'allocator' field. So it
// cannot be treated like a normal pointer, since it does not fit into an
// `Immediate`. Yeah, it is quite terrible. But many visitors want to do
// something with "all boxed pointers", so we handle this mess for them.
//
// When we hit a `Box`, we do not do the usual `visit_aggregate`; instead,
// we (a) call `visit_box` on the pointer value, and (b) recurse on the
// allocator field. We also assert tons of things to ensure we do not miss
// any other fields.
// `Box` has two fields: the pointer we care about, and the allocator.
assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields");
let (unique_ptr, alloc) =
(v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?);
// Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`...
// (which means another 2 fields, the second of which is a `PhantomData`)
assert_eq!(unique_ptr.layout().fields.count(), 2);
let (nonnull_ptr, phantom) = (
unique_ptr.project_field(self.ecx(), 0)?,
unique_ptr.project_field(self.ecx(), 1)?,
);
assert!(
phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()),
"2nd field of `Unique` should be PhantomData but is {:?}",
phantom.layout().ty,
);
// ... that contains a `NonNull`... (gladly, only a single field here)
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr
// ... whose only field finally is a raw ptr we can dereference.
self.visit_box(&raw_ptr)?;
// The second `Box` field is the allocator, which we recursively check for validity
// like in regular structs.
self.visit_field(v, 1, &alloc)?;
}
_ => {},
};
+1
View File
@@ -21,6 +21,7 @@
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
#![feature(is_some_with)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+264 -281
View File
@@ -59,7 +59,7 @@ fn nested(&self, state: &mut State<'_>, nested: Nested) {
Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)),
Nested::Body(id) => state.print_expr(&self.body(id).value),
Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat),
Nested::BodyParamPat(id, i) => state.print_pat(self.body(id).params[i].pat),
}
}
}
@@ -74,37 +74,37 @@ pub struct State<'a> {
impl<'a> State<'a> {
pub fn print_node(&mut self, node: Node<'_>) {
match node {
Node::Param(a) => self.print_param(&a),
Node::Item(a) => self.print_item(&a),
Node::ForeignItem(a) => self.print_foreign_item(&a),
Node::Param(a) => self.print_param(a),
Node::Item(a) => self.print_item(a),
Node::ForeignItem(a) => self.print_foreign_item(a),
Node::TraitItem(a) => self.print_trait_item(a),
Node::ImplItem(a) => self.print_impl_item(a),
Node::Variant(a) => self.print_variant(&a),
Node::AnonConst(a) => self.print_anon_const(&a),
Node::Expr(a) => self.print_expr(&a),
Node::Stmt(a) => self.print_stmt(&a),
Node::PathSegment(a) => self.print_path_segment(&a),
Node::Ty(a) => self.print_type(&a),
Node::TypeBinding(a) => self.print_type_binding(&a),
Node::TraitRef(a) => self.print_trait_ref(&a),
Node::Pat(a) => self.print_pat(&a),
Node::Arm(a) => self.print_arm(&a),
Node::Variant(a) => self.print_variant(a),
Node::AnonConst(a) => self.print_anon_const(a),
Node::Expr(a) => self.print_expr(a),
Node::Stmt(a) => self.print_stmt(a),
Node::PathSegment(a) => self.print_path_segment(a),
Node::Ty(a) => self.print_type(a),
Node::TypeBinding(a) => self.print_type_binding(a),
Node::TraitRef(a) => self.print_trait_ref(a),
Node::Pat(a) => self.print_pat(a),
Node::Arm(a) => self.print_arm(a),
Node::Infer(_) => self.word("_"),
Node::Block(a) => {
// Containing cbox, will be closed by print-block at `}`.
self.cbox(INDENT_UNIT);
// Head-ibox, will be closed by print-block after `{`.
self.ibox(0);
self.print_block(&a)
self.print_block(a);
}
Node::Lifetime(a) => self.print_lifetime(&a),
Node::Lifetime(a) => self.print_lifetime(a),
Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
Node::Field(_) => panic!("cannot print Node::Field"),
// These cases do not carry enough information in the
// `hir_map` to reconstruct their full structure for pretty
// printing.
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
Node::Local(a) => self.print_local_decl(a),
Node::Crate(..) => panic!("cannot print Crate"),
}
}
@@ -266,7 +266,7 @@ pub fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut g
}
pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span);
}
pub fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
@@ -287,9 +287,9 @@ pub fn print_type(&mut self, ty: &hir::Ty<'_>) {
self.maybe_print_comment(ty.span.lo());
self.ibox(0);
match ty.kind {
hir::TyKind::Slice(ref ty) => {
hir::TyKind::Slice(ty) => {
self.word("[");
self.print_type(&ty);
self.print_type(ty);
self.word("]");
}
hir::TyKind::Ptr(ref mt) => {
@@ -304,23 +304,16 @@ pub fn print_type(&mut self, ty: &hir::Ty<'_>) {
hir::TyKind::Never => {
self.word("!");
}
hir::TyKind::Tup(ref elts) => {
hir::TyKind::Tup(elts) => {
self.popen();
self.commasep(Inconsistent, &elts, |s, ty| s.print_type(&ty));
self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty));
if elts.len() == 1 {
self.word(",");
}
self.pclose();
}
hir::TyKind::BareFn(ref f) => {
self.print_ty_fn(
f.abi,
f.unsafety,
&f.decl,
None,
&f.generic_params,
f.param_names,
);
hir::TyKind::BareFn(f) => {
self.print_ty_fn(f.abi, f.unsafety, f.decl, None, f.generic_params, f.param_names);
}
hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"),
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
@@ -344,9 +337,9 @@ pub fn print_type(&mut self, ty: &hir::Ty<'_>) {
self.print_lifetime(lifetime);
}
}
hir::TyKind::Array(ref ty, ref length) => {
hir::TyKind::Array(ty, ref length) => {
self.word("[");
self.print_type(&ty);
self.print_type(ty);
self.word("; ");
self.print_array_length(length);
self.word("]");
@@ -373,7 +366,7 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(self.attrs(item.hir_id()));
match item.kind {
hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => {
hir::ForeignItemKind::Fn(decl, arg_names, generics) => {
self.head("");
self.print_fn(
decl,
@@ -392,14 +385,14 @@ pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
self.word(";");
self.end() // end the outer fn box
}
hir::ForeignItemKind::Static(ref t, m) => {
hir::ForeignItemKind::Static(t, m) => {
self.head("static");
if m == hir::Mutability::Mut {
self.word_space("mut");
}
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&t);
self.print_type(t);
self.word(";");
self.end(); // end the head-ibox
self.end() // end the outer cbox
@@ -442,7 +435,7 @@ fn print_associated_type(
) {
self.word_space("type");
self.print_ident(ident);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
if let Some(bounds) = bounds {
self.print_bounds(":", bounds);
}
@@ -463,7 +456,7 @@ fn print_item_type(
) {
self.head("type");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
self.end(); // end the inner ibox
self.print_where_clause(generics);
@@ -494,7 +487,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.end(); // end inner head-block
self.end(); // end outer head-block
}
hir::ItemKind::Use(ref path, kind) => {
hir::ItemKind::Use(path, kind) => {
self.head("use");
self.print_path(path, false);
@@ -513,14 +506,14 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.end(); // end inner head-block
self.end(); // end outer head-block
}
hir::ItemKind::Static(ref ty, m, expr) => {
hir::ItemKind::Static(ty, m, expr) => {
self.head("static");
if m == hir::Mutability::Mut {
self.word_space("mut");
}
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&ty);
self.print_type(ty);
self.space();
self.end(); // end the head-ibox
@@ -529,11 +522,11 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.word(";");
self.end(); // end the outer cbox
}
hir::ItemKind::Const(ref ty, expr) => {
hir::ItemKind::Const(ty, expr) => {
self.head("const");
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&ty);
self.print_type(ty);
self.space();
self.end(); // end the head-ibox
@@ -542,10 +535,10 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.word(";");
self.end(); // end the outer cbox
}
hir::ItemKind::Fn(ref sig, ref param_names, body) => {
hir::ItemKind::Fn(ref sig, param_names, body) => {
self.head("");
self.print_fn(
&sig.decl,
sig.decl,
sig.header,
Some(item.ident.name),
param_names,
@@ -578,22 +571,22 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
}
self.bclose(item.span);
}
hir::ItemKind::GlobalAsm(ref asm) => {
hir::ItemKind::GlobalAsm(asm) => {
self.head("global_asm!");
self.print_inline_asm(asm);
self.end()
}
hir::ItemKind::TyAlias(ref ty, ref generics) => {
self.print_item_type(item, &generics, |state| {
hir::ItemKind::TyAlias(ty, generics) => {
self.print_item_type(item, generics, |state| {
state.word_space("=");
state.print_type(&ty);
state.print_type(ty);
});
}
hir::ItemKind::OpaqueTy(ref opaque_ty) => {
self.print_item_type(item, &opaque_ty.generics, |state| {
self.print_item_type(item, opaque_ty.generics, |state| {
let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len());
for b in opaque_ty.bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
for b in opaque_ty.bounds {
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
state.space();
state.word_space("for ?");
state.print_trait_ref(&ptr.trait_ref);
@@ -604,39 +597,39 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
state.print_bounds("= impl", real_bounds);
});
}
hir::ItemKind::Enum(ref enum_definition, ref params) => {
hir::ItemKind::Enum(ref enum_definition, params) => {
self.print_enum_def(enum_definition, params, item.ident.name, item.span);
}
hir::ItemKind::Struct(ref struct_def, ref generics) => {
hir::ItemKind::Struct(ref struct_def, generics) => {
self.head("struct");
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Union(ref struct_def, ref generics) => {
hir::ItemKind::Union(ref struct_def, generics) => {
self.head("union");
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Impl(hir::Impl {
hir::ItemKind::Impl(&hir::Impl {
unsafety,
polarity,
defaultness,
constness,
defaultness_span: _,
ref generics,
generics,
ref of_trait,
ref self_ty,
self_ty,
items,
}) => {
self.head("");
self.print_defaultness(*defaultness);
self.print_unsafety(*unsafety);
self.print_defaultness(defaultness);
self.print_unsafety(unsafety);
self.word_nbsp("impl");
if !generics.params.is_empty() {
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
self.space();
}
if *constness == hir::Constness::Const {
if constness == hir::Constness::Const {
self.word_nbsp("const");
}
@@ -644,33 +637,33 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.word("!");
}
if let Some(ref t) = of_trait {
if let Some(t) = of_trait {
self.print_trait_ref(t);
self.space();
self.word_space("for");
}
self.print_type(&self_ty);
self.print_type(self_ty);
self.print_where_clause(generics);
self.space();
self.bopen();
self.print_inner_attributes(attrs);
for impl_item in *items {
for impl_item in items {
self.ann.nested(self, Nested::ImplItem(impl_item.id));
}
self.bclose(item.span);
}
hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => {
hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => {
self.head("");
self.print_is_auto(is_auto);
self.print_unsafety(unsafety);
self.word_nbsp("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
for b in bounds {
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
@@ -687,14 +680,14 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
}
self.bclose(item.span);
}
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
hir::ItemKind::TraitAlias(generics, bounds) => {
self.head("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
for b in bounds {
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
@@ -714,7 +707,7 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
}
pub fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) {
self.print_path(&t.path, false)
self.print_path(t.path, false);
}
fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) {
@@ -726,8 +719,8 @@ fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_
}
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) {
self.print_formal_generic_params(&t.bound_generic_params);
self.print_trait_ref(&t.trait_ref)
self.print_formal_generic_params(t.bound_generic_params);
self.print_trait_ref(&t.trait_ref);
}
pub fn print_enum_def(
@@ -739,10 +732,10 @@ pub fn print_enum_def(
) {
self.head("enum");
self.print_name(name);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
self.print_where_clause(generics);
self.space();
self.print_variants(&enum_definition.variants, span)
self.print_variants(enum_definition.variants, span);
}
pub fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) {
@@ -776,7 +769,7 @@ pub fn print_struct(
print_finalizer: bool,
) {
self.print_name(name);
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
match struct_def {
hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
if let hir::VariantData::Tuple(..) = struct_def {
@@ -784,7 +777,7 @@ pub fn print_struct(
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo());
s.print_outer_attributes(s.attrs(field.hir_id));
s.print_type(&field.ty)
s.print_type(field.ty);
});
self.pclose();
}
@@ -807,7 +800,7 @@ pub fn print_struct(
self.print_outer_attributes(self.attrs(field.hir_id));
self.print_ident(field.ident);
self.word_nbsp(":");
self.print_type(&field.ty);
self.print_type(field.ty);
self.word(",");
}
@@ -819,7 +812,7 @@ pub fn print_struct(
pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
self.head("");
let generics = hir::Generics::empty();
self.print_struct(&v.data, &generics, v.ident.name, v.span, false);
self.print_struct(&v.data, generics, v.ident.name, v.span, false);
if let Some(ref d) = v.disr_expr {
self.space();
self.word_space("=");
@@ -834,7 +827,7 @@ pub fn print_method_sig(
arg_names: &[Ident],
body_id: Option<hir::BodyId>,
) {
self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id)
self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
}
pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
@@ -843,28 +836,23 @@ pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
self.maybe_print_comment(ti.span.lo());
self.print_outer_attributes(self.attrs(ti.hir_id()));
match ti.kind {
hir::TraitItemKind::Const(ref ty, default) => {
self.print_associated_const(ti.ident, &ty, default);
hir::TraitItemKind::Const(ty, default) => {
self.print_associated_const(ti.ident, ty, default);
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None);
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => {
self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None);
self.word(";");
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
self.head("");
self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body));
self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
self.print_associated_type(
ti.ident,
&ti.generics,
Some(bounds),
default.as_ref().map(|ty| &**ty),
);
hir::TraitItemKind::Type(bounds, default) => {
self.print_associated_type(ti.ident, ti.generics, Some(bounds), default);
}
}
self.ann.post(self, AnnNode::SubItem(ti.hir_id()))
@@ -877,19 +865,19 @@ pub fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
self.print_outer_attributes(self.attrs(ii.hir_id()));
match ii.kind {
hir::ImplItemKind::Const(ref ty, expr) => {
self.print_associated_const(ii.ident, &ty, Some(expr));
hir::ImplItemKind::Const(ty, expr) => {
self.print_associated_const(ii.ident, ty, Some(expr));
}
hir::ImplItemKind::Fn(ref sig, body) => {
self.head("");
self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body));
self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
}
hir::ImplItemKind::TyAlias(ref ty) => {
self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
hir::ImplItemKind::TyAlias(ty) => {
self.print_associated_type(ii.ident, ii.generics, None, Some(ty));
}
}
self.ann.post(self, AnnNode::SubItem(ii.hir_id()))
@@ -904,10 +892,10 @@ pub fn print_local(&mut self, init: Option<&hir::Expr<'_>>, decl: impl Fn(&mut S
decl(self);
self.end();
if let Some(ref init) = init {
if let Some(init) = init {
self.nbsp();
self.word_space("=");
self.print_expr(&init);
self.print_expr(init);
}
self.end()
}
@@ -915,17 +903,17 @@ pub fn print_local(&mut self, init: Option<&hir::Expr<'_>>, decl: impl Fn(&mut S
pub fn print_stmt(&mut self, st: &hir::Stmt<'_>) {
self.maybe_print_comment(st.span.lo());
match st.kind {
hir::StmtKind::Local(ref loc) => {
self.print_local(loc.init, |this| this.print_local_decl(&loc));
hir::StmtKind::Local(loc) => {
self.print_local(loc.init, |this| this.print_local_decl(loc));
}
hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
hir::StmtKind::Expr(ref expr) => {
hir::StmtKind::Expr(expr) => {
self.space_if_not_bol();
self.print_expr(&expr);
self.print_expr(expr);
}
hir::StmtKind::Semi(ref expr) => {
hir::StmtKind::Semi(expr) => {
self.space_if_not_bol();
self.print_expr(&expr);
self.print_expr(expr);
self.word(";");
}
}
@@ -966,9 +954,9 @@ pub fn print_block_maybe_unclosed(
for st in blk.stmts {
self.print_stmt(st);
}
if let Some(ref expr) = blk.expr {
if let Some(expr) = blk.expr {
self.space_if_not_bol();
self.print_expr(&expr);
self.print_expr(expr);
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
}
self.bclose_maybe_open(blk.span, close_box);
@@ -979,21 +967,21 @@ fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
if let Some(els_inner) = els {
match els_inner.kind {
// Another `else if` block.
hir::ExprKind::If(ref i, ref then, ref e) => {
hir::ExprKind::If(i, then, e) => {
self.cbox(INDENT_UNIT - 1);
self.ibox(0);
self.word(" else if ");
self.print_expr_as_cond(&i);
self.print_expr_as_cond(i);
self.space();
self.print_expr(&then);
self.print_else(e.as_ref().map(|e| &**e))
self.print_expr(then);
self.print_else(e);
}
// Final `else` block.
hir::ExprKind::Block(ref b, _) => {
hir::ExprKind::Block(b, _) => {
self.cbox(INDENT_UNIT - 1);
self.ibox(0);
self.word(" else ");
self.print_block(&b)
self.print_block(b);
}
// Constraints would be great here!
_ => {
@@ -1048,7 +1036,7 @@ fn print_expr_cond_paren(&mut self, expr: &hir::Expr<'_>, needs_par: bool) {
if needs_par {
self.popen();
}
if let hir::ExprKind::DropTemps(ref actual_expr) = expr.kind {
if let hir::ExprKind::DropTemps(actual_expr) = expr.kind {
self.print_expr(actual_expr);
} else {
self.print_expr(expr);
@@ -1114,7 +1102,7 @@ fn print_expr_struct(
&mut self,
qpath: &hir::QPath<'_>,
fields: &[hir::ExprField<'_>],
wth: &Option<&hir::Expr<'_>>,
wth: Option<&hir::Expr<'_>>,
) {
self.print_qpath(qpath, true);
self.word("{");
@@ -1127,28 +1115,24 @@ fn print_expr_struct(
s.print_ident(field.ident);
s.word_space(":");
}
s.print_expr(&field.expr);
s.print_expr(field.expr);
s.end()
},
|f| f.span,
);
match *wth {
Some(ref expr) => {
self.ibox(INDENT_UNIT);
if !fields.is_empty() {
self.word(",");
self.space();
}
self.word("..");
self.print_expr(&expr);
self.end();
}
_ => {
if !fields.is_empty() {
self.word(",")
}
if let Some(expr) = wth {
self.ibox(INDENT_UNIT);
if !fields.is_empty() {
self.word(",");
self.space();
}
self.word("..");
self.print_expr(expr);
self.end();
} else if !fields.is_empty() {
self.word(",");
}
self.word("}");
}
@@ -1249,18 +1233,17 @@ enum AsmArg<'a> {
Options(ast::InlineAsmOptions),
}
let mut args =
vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(&asm.template))];
let mut args = vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(asm.template))];
args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
if !asm.options.is_empty() {
args.push(AsmArg::Options(asm.options));
}
self.popen();
self.commasep(Consistent, &args, |s, arg| match arg {
AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
AsmArg::Operand(op) => match op {
hir::InlineAsmOperand::In { reg, expr } => {
self.commasep(Consistent, &args, |s, arg| match *arg {
AsmArg::Template(ref template) => s.print_string(template, ast::StrStyle::Cooked),
AsmArg::Operand(op) => match *op {
hir::InlineAsmOperand::In { reg, ref expr } => {
s.word("in");
s.popen();
s.word(format!("{}", reg));
@@ -1268,8 +1251,8 @@ enum AsmArg<'a> {
s.space();
s.print_expr(expr);
}
hir::InlineAsmOperand::Out { reg, late, expr } => {
s.word(if *late { "lateout" } else { "out" });
hir::InlineAsmOperand::Out { reg, late, ref expr } => {
s.word(if late { "lateout" } else { "out" });
s.popen();
s.word(format!("{}", reg));
s.pclose();
@@ -1279,16 +1262,16 @@ enum AsmArg<'a> {
None => s.word("_"),
}
}
hir::InlineAsmOperand::InOut { reg, late, expr } => {
s.word(if *late { "inlateout" } else { "inout" });
hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
s.word(if late { "inlateout" } else { "inout" });
s.popen();
s.word(format!("{}", reg));
s.pclose();
s.space();
s.print_expr(expr);
}
hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
s.word(if *late { "inlateout" } else { "inout" });
hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
s.word(if late { "inlateout" } else { "inout" });
s.popen();
s.word(format!("{}", reg));
s.pclose();
@@ -1301,17 +1284,17 @@ enum AsmArg<'a> {
None => s.word("_"),
}
}
hir::InlineAsmOperand::Const { anon_const } => {
hir::InlineAsmOperand::Const { ref anon_const } => {
s.word("const");
s.space();
s.print_anon_const(anon_const);
}
hir::InlineAsmOperand::SymFn { anon_const } => {
hir::InlineAsmOperand::SymFn { ref anon_const } => {
s.word("sym_fn");
s.space();
s.print_anon_const(anon_const);
}
hir::InlineAsmOperand::SymStatic { path, def_id: _ } => {
hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => {
s.word("sym_static");
s.space();
s.print_qpath(path, true);
@@ -1363,57 +1346,57 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind {
hir::ExprKind::Box(ref expr) => {
hir::ExprKind::Box(expr) => {
self.word_space("box");
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
}
hir::ExprKind::Array(ref exprs) => {
hir::ExprKind::Array(exprs) => {
self.print_expr_vec(exprs);
}
hir::ExprKind::ConstBlock(ref anon_const) => {
self.print_expr_anon_const(anon_const);
}
hir::ExprKind::Repeat(ref element, ref count) => {
self.print_expr_repeat(&element, count);
hir::ExprKind::Repeat(element, ref count) => {
self.print_expr_repeat(element, count);
}
hir::ExprKind::Struct(ref qpath, fields, ref wth) => {
hir::ExprKind::Struct(qpath, fields, wth) => {
self.print_expr_struct(qpath, fields, wth);
}
hir::ExprKind::Tup(ref exprs) => {
hir::ExprKind::Tup(exprs) => {
self.print_expr_tup(exprs);
}
hir::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(&func, args);
hir::ExprKind::Call(func, args) => {
self.print_expr_call(func, args);
}
hir::ExprKind::MethodCall(ref segment, ref args, _) => {
hir::ExprKind::MethodCall(segment, args, _) => {
self.print_expr_method_call(segment, args);
}
hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, &lhs, &rhs);
hir::ExprKind::Binary(op, lhs, rhs) => {
self.print_expr_binary(op, lhs, rhs);
}
hir::ExprKind::Unary(op, ref expr) => {
self.print_expr_unary(op, &expr);
hir::ExprKind::Unary(op, expr) => {
self.print_expr_unary(op, expr);
}
hir::ExprKind::AddrOf(k, m, ref expr) => {
self.print_expr_addr_of(k, m, &expr);
hir::ExprKind::AddrOf(k, m, expr) => {
self.print_expr_addr_of(k, m, expr);
}
hir::ExprKind::Lit(ref lit) => {
self.print_literal(&lit);
self.print_literal(lit);
}
hir::ExprKind::Cast(ref expr, ref ty) => {
hir::ExprKind::Cast(expr, ty) => {
let prec = AssocOp::As.precedence() as i8;
self.print_expr_maybe_paren(&expr, prec);
self.print_expr_maybe_paren(expr, prec);
self.space();
self.word_space("as");
self.print_type(&ty);
self.print_type(ty);
}
hir::ExprKind::Type(ref expr, ref ty) => {
hir::ExprKind::Type(expr, ty) => {
let prec = AssocOp::Colon.precedence() as i8;
self.print_expr_maybe_paren(&expr, prec);
self.print_expr_maybe_paren(expr, prec);
self.word_space(":");
self.print_type(&ty);
self.print_type(ty);
}
hir::ExprKind::DropTemps(ref init) => {
hir::ExprKind::DropTemps(init) => {
// Print `{`:
self.cbox(INDENT_UNIT);
self.ibox(0);
@@ -1431,25 +1414,25 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
// Print `}`:
self.bclose_maybe_open(expr.span, true);
}
hir::ExprKind::Let(hir::Let { pat, ty, init, .. }) => {
self.print_let(pat, *ty, init);
hir::ExprKind::Let(&hir::Let { pat, ty, init, .. }) => {
self.print_let(pat, ty, init);
}
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e));
hir::ExprKind::If(test, blk, elseopt) => {
self.print_if(test, blk, elseopt);
}
hir::ExprKind::Loop(ref blk, opt_label, _, _) => {
hir::ExprKind::Loop(blk, opt_label, _, _) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
}
self.head("loop");
self.print_block(&blk);
self.print_block(blk);
}
hir::ExprKind::Match(ref expr, arms, _) => {
hir::ExprKind::Match(expr, arms, _) => {
self.cbox(INDENT_UNIT);
self.ibox(INDENT_UNIT);
self.word_nbsp("match");
self.print_expr_as_cond(&expr);
self.print_expr_as_cond(expr);
self.space();
self.bopen();
for arm in arms {
@@ -1460,7 +1443,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
hir::ExprKind::Closure {
capture_clause,
bound_generic_params,
ref fn_decl,
fn_decl,
body,
fn_decl_span: _,
movability: _,
@@ -1468,7 +1451,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.print_formal_generic_params(bound_generic_params);
self.print_capture_clause(capture_clause);
self.print_closure_params(&fn_decl, body);
self.print_closure_params(fn_decl, body);
self.space();
// This is a bare expression.
@@ -1480,7 +1463,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
// empty box to satisfy the close.
self.ibox(0);
}
hir::ExprKind::Block(ref blk, opt_label) => {
hir::ExprKind::Block(blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
@@ -1489,42 +1472,42 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.cbox(INDENT_UNIT);
// head-box, will be closed by print-block after `{`
self.ibox(0);
self.print_block(&blk);
self.print_block(blk);
}
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
hir::ExprKind::Assign(lhs, rhs, _) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(&lhs, prec + 1);
self.print_expr_maybe_paren(lhs, prec + 1);
self.space();
self.word_space("=");
self.print_expr_maybe_paren(&rhs, prec);
self.print_expr_maybe_paren(rhs, prec);
}
hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
hir::ExprKind::AssignOp(op, lhs, rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(&lhs, prec + 1);
self.print_expr_maybe_paren(lhs, prec + 1);
self.space();
self.word(op.node.as_str());
self.word_space("=");
self.print_expr_maybe_paren(&rhs, prec);
self.print_expr_maybe_paren(rhs, prec);
}
hir::ExprKind::Field(ref expr, ident) => {
hir::ExprKind::Field(expr, ident) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(ident);
}
hir::ExprKind::Index(ref expr, ref index) => {
self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX);
hir::ExprKind::Index(expr, index) => {
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
self.word("[");
self.print_expr(&index);
self.print_expr(index);
self.word("]");
}
hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true),
hir::ExprKind::Break(destination, ref opt_expr) => {
hir::ExprKind::Break(destination, opt_expr) => {
self.word("break");
if let Some(label) = destination.label {
self.space();
self.print_ident(label.ident);
}
if let Some(ref expr) = *opt_expr {
if let Some(expr) = opt_expr {
self.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
@@ -1536,20 +1519,20 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.print_ident(label.ident);
}
}
hir::ExprKind::Ret(ref result) => {
hir::ExprKind::Ret(result) => {
self.word("return");
if let Some(ref expr) = *result {
if let Some(expr) = result {
self.word(" ");
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
hir::ExprKind::InlineAsm(ref asm) => {
hir::ExprKind::InlineAsm(asm) => {
self.word("asm!");
self.print_inline_asm(asm);
}
hir::ExprKind::Yield(ref expr, _) => {
hir::ExprKind::Yield(expr, _) => {
self.word_space("yield");
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
hir::ExprKind::Err => {
self.popen();
@@ -1562,10 +1545,10 @@ pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
}
pub fn print_local_decl(&mut self, loc: &hir::Local<'_>) {
self.print_pat(&loc.pat);
if let Some(ref ty) = loc.ty {
self.print_pat(loc.pat);
if let Some(ty) = loc.ty {
self.word_space(":");
self.print_type(&ty);
self.print_type(ty);
}
}
@@ -1596,8 +1579,8 @@ pub fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool) {
match *qpath {
hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params),
hir::QPath::Resolved(Some(ref qself), ref path) => {
hir::QPath::Resolved(None, path) => self.print_path(path, colons_before_params),
hir::QPath::Resolved(Some(qself), path) => {
self.word("<");
self.print_type(qself);
self.space();
@@ -1627,11 +1610,11 @@ pub fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool
colons_before_params,
)
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
hir::QPath::TypeRelative(qself, item_segment) => {
// If we've got a compound-qualified-path, let's push an additional pair of angle
// brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just
// `A::B::C` (since the latter could be ambiguous to the user)
if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind {
if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = qself.kind {
self.print_type(qself);
} else {
self.word("<");
@@ -1663,7 +1646,7 @@ fn print_generic_args(
) {
if generic_args.parenthesized {
self.word("(");
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty));
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty));
self.word(")");
self.space_if_not_bol();
@@ -1694,7 +1677,7 @@ fn print_generic_args(
start_or_comma(self);
self.commasep(
Inconsistent,
&generic_args.args,
generic_args.args,
|s, generic_arg| match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
GenericArg::Lifetime(_) => {}
@@ -1712,7 +1695,7 @@ fn print_generic_args(
self.word("..");
}
for binding in generic_args.bindings.iter() {
for binding in generic_args.bindings {
start_or_comma(self);
self.print_type_binding(binding);
}
@@ -1731,7 +1714,7 @@ pub fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) {
hir::TypeBindingKind::Equality { ref term } => {
self.word_space("=");
match term {
Term::Ty(ref ty) => self.print_type(ty),
Term::Ty(ty) => self.print_type(ty),
Term::Const(ref c) => self.print_anon_const(c),
}
}
@@ -1748,7 +1731,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
// is that it doesn't matter
match pat.kind {
PatKind::Wild => self.word("_"),
PatKind::Binding(binding_mode, _, ident, ref sub) => {
PatKind::Binding(binding_mode, _, ident, sub) => {
match binding_mode {
hir::BindingAnnotation::Ref => {
self.word_nbsp("ref");
@@ -1764,33 +1747,33 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
}
}
self.print_ident(ident);
if let Some(ref p) = *sub {
if let Some(p) = sub {
self.word("@");
self.print_pat(&p);
self.print_pat(p);
}
}
PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
PatKind::TupleStruct(ref qpath, elts, ddpos) => {
self.print_qpath(qpath, true);
self.popen();
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 {
self.word_space(",");
}
self.word("..");
if ddpos != elts.len() {
self.word(",");
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
}
} else {
self.commasep(Inconsistent, &elts, |s, p| s.print_pat(&p));
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
}
self.pclose();
}
PatKind::Path(ref qpath) => {
self.print_qpath(qpath, true);
}
PatKind::Struct(ref qpath, ref fields, etc) => {
PatKind::Struct(ref qpath, fields, etc) => {
self.print_qpath(qpath, true);
self.nbsp();
self.word("{");
@@ -1800,14 +1783,14 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
}
self.commasep_cmnt(
Consistent,
&fields,
fields,
|s, f| {
s.cbox(INDENT_UNIT);
if !f.is_shorthand {
s.print_ident(f.ident);
s.word_nbsp(":");
}
s.print_pat(&f.pat);
s.print_pat(f.pat);
s.end()
},
|f| f.pat.span,
@@ -1823,58 +1806,58 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
}
self.word("}");
}
PatKind::Or(ref pats) => {
self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(&p));
PatKind::Or(pats) => {
self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p));
}
PatKind::Tuple(ref elts, ddpos) => {
PatKind::Tuple(elts, ddpos) => {
self.popen();
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p));
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 {
self.word_space(",");
}
self.word("..");
if ddpos != elts.len() {
self.word(",");
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p));
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
}
} else {
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p));
self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
if elts.len() == 1 {
self.word(",");
}
}
self.pclose();
}
PatKind::Box(ref inner) => {
PatKind::Box(inner) => {
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
self.word("box ");
if is_range_inner {
self.popen();
}
self.print_pat(&inner);
self.print_pat(inner);
if is_range_inner {
self.pclose();
}
}
PatKind::Ref(ref inner, mutbl) => {
PatKind::Ref(inner, mutbl) => {
let is_range_inner = matches!(inner.kind, PatKind::Range(..));
self.word("&");
self.word(mutbl.prefix_str());
if is_range_inner {
self.popen();
}
self.print_pat(&inner);
self.print_pat(inner);
if is_range_inner {
self.pclose();
}
}
PatKind::Lit(ref e) => self.print_expr(&e),
PatKind::Range(ref begin, ref end, ref end_kind) => {
PatKind::Lit(e) => self.print_expr(e),
PatKind::Range(begin, end, end_kind) => {
if let Some(expr) = begin {
self.print_expr(expr);
}
match *end_kind {
match end_kind {
RangeEnd::Included => self.word("..."),
RangeEnd::Excluded => self.word(".."),
}
@@ -1882,24 +1865,24 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
self.print_expr(expr);
}
}
PatKind::Slice(ref before, ref slice, ref after) => {
PatKind::Slice(before, slice, after) => {
self.word("[");
self.commasep(Inconsistent, &before, |s, p| s.print_pat(&p));
if let Some(ref p) = *slice {
self.commasep(Inconsistent, before, |s, p| s.print_pat(p));
if let Some(p) = slice {
if !before.is_empty() {
self.word_space(",");
}
if let PatKind::Wild = p.kind {
// Print nothing.
} else {
self.print_pat(&p);
self.print_pat(p);
}
self.word("..");
if !after.is_empty() {
self.word_space(",");
}
}
self.commasep(Inconsistent, &after, |s, p| s.print_pat(&p));
self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
self.word("]");
}
}
@@ -1908,7 +1891,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat<'_>) {
pub fn print_param(&mut self, arg: &hir::Param<'_>) {
self.print_outer_attributes(self.attrs(arg.hir_id));
self.print_pat(&arg.pat);
self.print_pat(arg.pat);
}
pub fn print_arm(&mut self, arm: &hir::Arm<'_>) {
@@ -1920,32 +1903,32 @@ pub fn print_arm(&mut self, arm: &hir::Arm<'_>) {
self.cbox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Arm(arm));
self.ibox(0);
self.print_outer_attributes(&self.attrs(arm.hir_id));
self.print_pat(&arm.pat);
self.print_outer_attributes(self.attrs(arm.hir_id));
self.print_pat(arm.pat);
self.space();
if let Some(ref g) = arm.guard {
match g {
match *g {
hir::Guard::If(e) => {
self.word_space("if");
self.print_expr(&e);
self.print_expr(e);
self.space();
}
hir::Guard::IfLet(hir::Let { pat, ty, init, .. }) => {
hir::Guard::IfLet(&hir::Let { pat, ty, init, .. }) => {
self.word_nbsp("if");
self.print_let(pat, *ty, init);
self.print_let(pat, ty, init);
}
}
}
self.word_space("=>");
match arm.body.kind {
hir::ExprKind::Block(ref blk, opt_label) => {
hir::ExprKind::Block(blk, opt_label) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
}
// the block will close the pattern's ibox
self.print_block_unclosed(&blk);
self.print_block_unclosed(blk);
// If it is a user-provided unsafe block, print a comma after it
if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules
@@ -1955,7 +1938,7 @@ pub fn print_arm(&mut self, arm: &hir::Arm<'_>) {
}
_ => {
self.end(); // close the ibox for the pattern
self.print_expr(&arm.body);
self.print_expr(arm.body);
self.word(",");
}
}
@@ -1978,13 +1961,13 @@ pub fn print_fn(
self.nbsp();
self.print_name(name);
}
self.print_generic_params(&generics.params);
self.print_generic_params(generics.params);
self.popen();
let mut i = 0;
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
assert!(arg_names.is_empty() || body_id.is_none());
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
self.commasep(Inconsistent, decl.inputs, |s, ty| {
s.ibox(INDENT_UNIT);
if let Some(arg_name) = arg_names.get(i) {
s.word(arg_name.to_string());
@@ -2011,7 +1994,7 @@ pub fn print_fn(
fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) {
self.word("|");
let mut i = 0;
self.commasep(Inconsistent, &decl.inputs, |s, ty| {
self.commasep(Inconsistent, decl.inputs, |s, ty| {
s.ibox(INDENT_UNIT);
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
@@ -2035,8 +2018,8 @@ fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId)
self.space_if_not_bol();
self.word_space("->");
match decl.output {
hir::FnRetTy::Return(ref ty) => {
self.print_type(&ty);
hir::FnRetTy::Return(ty) => {
self.print_type(ty);
self.maybe_print_comment(ty.span.lo());
}
hir::FnRetTy::DefaultReturn(..) => unreachable!(),
@@ -2107,20 +2090,20 @@ pub fn print_generic_param(&mut self, param: &GenericParam<'_>) {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => {
GenericParamKind::Type { default, .. } => {
if let Some(default) = default {
self.space();
self.word_space("=");
self.print_type(&default)
self.print_type(default);
}
}
GenericParamKind::Const { ref ty, ref default } => {
GenericParamKind::Const { ty, ref default } => {
self.word_space(":");
self.print_type(ty);
if let Some(ref default) = default {
if let Some(default) = default {
self.space();
self.word_space("=");
self.print_anon_const(&default)
self.print_anon_const(default);
}
}
}
@@ -2143,7 +2126,7 @@ pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
self.word_space(",");
}
match predicate {
match *predicate {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params,
bounded_ty,
@@ -2151,11 +2134,11 @@ pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
..
}) => {
self.print_formal_generic_params(bound_generic_params);
self.print_type(&bounded_ty);
self.print_bounds(":", *bounds);
self.print_type(bounded_ty);
self.print_bounds(":", bounds);
}
hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
ref lifetime,
bounds,
..
}) => {
@@ -2200,7 +2183,7 @@ pub fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
pub fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) {
self.print_mutability(mt.mutbl, print_const);
self.print_type(&mt.ty)
self.print_type(mt.ty);
}
pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
@@ -2213,11 +2196,11 @@ pub fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
self.word_space("->");
match decl.output {
hir::FnRetTy::DefaultReturn(..) => unreachable!(),
hir::FnRetTy::Return(ref ty) => self.print_type(&ty),
hir::FnRetTy::Return(ty) => self.print_type(ty),
}
self.end();
if let hir::FnRetTy::Return(ref output) = decl.output {
if let hir::FnRetTy::Return(output) = decl.output {
self.maybe_print_comment(output.span.lo());
}
}
@@ -2243,7 +2226,7 @@ pub fn print_ty_fn(
asyncness: hir::IsAsync::NotAsync,
},
name,
&generics,
generics,
arg_names,
None,
);
@@ -2312,7 +2295,7 @@ fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool {
match *stmt {
hir::StmtKind::Local(_) => true,
hir::StmtKind::Item(_) => false,
hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e),
hir::StmtKind::Semi(..) => false,
}
}
@@ -2351,22 +2334,22 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
match value.kind {
hir::ExprKind::Struct(..) => true,
hir::ExprKind::Assign(ref lhs, ref rhs, _)
| hir::ExprKind::AssignOp(_, ref lhs, ref rhs)
| hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
hir::ExprKind::Assign(lhs, rhs, _)
| hir::ExprKind::AssignOp(_, lhs, rhs)
| hir::ExprKind::Binary(_, lhs, rhs) => {
// `X { y: 1 } + X { y: 2 }`
contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs)
}
hir::ExprKind::Unary(_, ref x)
| hir::ExprKind::Cast(ref x, _)
| hir::ExprKind::Type(ref x, _)
| hir::ExprKind::Field(ref x, _)
| hir::ExprKind::Index(ref x, _) => {
hir::ExprKind::Unary(_, x)
| hir::ExprKind::Cast(x, _)
| hir::ExprKind::Type(x, _)
| hir::ExprKind::Field(x, _)
| hir::ExprKind::Index(x, _) => {
// `&X { y: 1 }, X { y: 1 }.y`
contains_exterior_struct_lit(&x)
contains_exterior_struct_lit(x)
}
hir::ExprKind::MethodCall(.., ref exprs, _) => {
hir::ExprKind::MethodCall(.., exprs, _) => {
// `X { y: 1 }.bar(...)`
contains_exterior_struct_lit(&exprs[0])
}
@@ -315,8 +315,6 @@ pub fn emit_inference_failure_err(
body_id: Option<hir::BodyId>,
failure_span: Span,
arg: GenericArg<'tcx>,
// FIXME(#94483): Either use this or remove it.
_impl_candidates: Vec<ty::TraitRef<'tcx>>,
error_code: TypeAnnotationNeeded,
should_label_span: bool,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
@@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> {
},
}
impl<'tcx> InferSource<'tcx> {
fn from_expansion(&self) -> bool {
let source_from_expansion = match self.kind {
InferSourceKind::LetBinding { insert_span, .. }
| InferSourceKind::ClosureArg { insert_span, .. }
| InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
receiver.span.from_expansion()
}
InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion)
}
};
source_from_expansion || self.span.from_expansion()
}
}
impl<'tcx> InferSourceKind<'tcx> {
fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String {
match *self {
@@ -604,43 +619,65 @@ fn new(
/// Sources with a small cost are prefer and should result
/// in a clearer and idiomatic suggestion.
fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
let tcx = self.infcx.tcx;
fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize {
match arg.unpack() {
GenericArgKind::Lifetime(_) => 0, // erased
GenericArgKind::Type(ty) => ty_cost(ty),
GenericArgKind::Const(_) => 3, // some non-zero value
}
#[derive(Clone, Copy)]
struct CostCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
}
fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize {
match ty.kind() {
ty::Closure(..) => 100,
ty::FnDef(..) => 20,
ty::FnPtr(..) => 10,
ty::Infer(..) => 0,
_ => 1,
impl<'tcx> CostCtxt<'tcx> {
fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
match arg.unpack() {
GenericArgKind::Lifetime(_) => 0, // erased
GenericArgKind::Type(ty) => self.ty_cost(ty),
GenericArgKind::Const(_) => 3, // some non-zero value
}
}
fn ty_cost(self, ty: Ty<'tcx>) -> usize {
match *ty.kind() {
ty::Closure(..) => 1000,
ty::FnDef(..) => 150,
ty::FnPtr(..) => 30,
ty::Adt(def, substs) => {
5 + self
.tcx
.generics_of(def.did())
.own_substs_no_defaults(self.tcx, substs)
.iter()
.map(|&arg| self.arg_cost(arg))
.sum::<usize>()
}
ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
ty::Infer(..) => 0,
_ => 1,
}
}
}
// The sources are listed in order of preference here.
match source.kind {
InferSourceKind::LetBinding { ty, .. } => ty_cost(ty),
InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty),
let tcx = self.infcx.tcx;
let ctx = CostCtxt { tcx };
let base_cost = match source.kind {
InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
InferSourceKind::GenericArg { def_id, generic_args, .. } => {
let variant_cost = match tcx.def_kind(def_id) {
DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::<u32>` and friends are ugly.
_ => 12,
// `None::<u32>` and friends are ugly.
DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
_ => 10,
};
variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::<usize>()
variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
}
InferSourceKind::FullyQualifiedMethodCall { substs, .. } => {
20 + substs.iter().map(|arg| arg_cost(arg)).sum::<usize>()
20 + substs.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
}
InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
}
}
};
let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 };
base_cost + suggestion_may_apply
}
/// Uses `fn source_cost` to determine whether this inference source is preferable to
@@ -648,6 +685,7 @@ fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize {
#[instrument(level = "debug", skip(self))]
fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
let cost = self.source_cost(&new_source) + self.attempt;
debug!(?cost);
self.attempt += 1;
if cost < self.infer_source_cost {
self.infer_source_cost = cost;
@@ -655,6 +693,11 @@ fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
}
}
fn node_substs_opt(&self, hir_id: HirId) -> Option<SubstsRef<'tcx>> {
let substs = self.typeck_results.node_substs_opt(hir_id);
self.infcx.resolve_vars_if_possible(substs)
}
fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
let ty = self.typeck_results.node_type_opt(hir_id);
self.infcx.resolve_vars_if_possible(ty)
@@ -737,7 +780,7 @@ fn expr_inferred_subst_iter(
let tcx = self.infcx.tcx;
match expr.kind {
hir::ExprKind::Path(ref path) => {
if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) {
if let Some(substs) = self.node_substs_opt(expr.hir_id) {
return self.path_inferred_subst_iter(expr.hir_id, substs, path);
}
}
@@ -765,7 +808,7 @@ fn expr_inferred_subst_iter(
if generics.has_impl_trait() {
None?
}
let substs = self.typeck_results.node_substs_opt(expr.hir_id)?;
let substs = self.node_substs_opt(expr.hir_id)?;
let span = tcx.hir().span(segment.hir_id?);
let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
InsertableGenericArgs {
@@ -980,8 +1023,10 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
debug!(?args);
let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(argument_index) =
generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg))
if let Some(argument_index) = generics
.own_substs(substs)
.iter()
.position(|&arg| self.generic_arg_contains_target(arg))
{
let substs = self.infcx.resolve_vars_if_possible(substs);
let generic_args = &generics.own_substs_no_defaults(tcx, substs)
@@ -1037,7 +1082,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
.any(|generics| generics.has_impl_trait())
};
if let ExprKind::MethodCall(path, args, span) = expr.kind
&& let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id)
&& let Some(substs) = self.node_substs_opt(expr.hir_id)
&& substs.iter().any(|arg| self.generic_arg_contains_target(arg))
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
&& self.infcx.tcx.trait_of_item(def_id).is_some()
@@ -160,12 +160,18 @@ pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> {
}
/// The information that makes up a memory access: offset and size.
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone)]
pub struct AllocRange {
pub start: Size,
pub size: Size,
}
impl fmt::Debug for AllocRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes())
}
}
/// Free-starting constructor for less syntactic overhead.
#[inline(always)]
pub fn alloc_range(start: Size, size: Size) -> AllocRange {
@@ -334,36 +334,30 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
p,
),
PointerUseAfterFree(a) => {
write!(f, "pointer to {} was dereferenced after this allocation got freed", a)
write!(f, "pointer to {a:?} was dereferenced after this allocation got freed")
}
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => {
write!(
f,
"{}{alloc_id} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
msg,
alloc_id = alloc_id,
"{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
alloc_size = alloc_size.bytes(),
ptr_offset = ptr_offset,
)
}
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!(
f,
"{}{alloc_id} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
msg,
alloc_id = alloc_id,
"{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
alloc_size = alloc_size.bytes(),
ptr_size = ptr_size.bytes(),
ptr_size_p = pluralize!(ptr_size.bytes()),
ptr_offset = ptr_offset,
),
DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
write!(f, "null pointer is not a valid pointer for this operation")
}
DanglingIntPointer(0, msg) => {
write!(f, "{}null pointer is not a valid pointer", msg)
write!(f, "{msg}null pointer is not a valid pointer")
}
DanglingIntPointer(i, msg) => {
write!(f, "{}0x{:x} is not a valid pointer", msg, i)
write!(f, "{msg}{i:#x} is not a valid pointer")
}
AlignmentCheckFailed { required, has } => write!(
f,
@@ -371,8 +365,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
has.bytes(),
required.bytes()
),
WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a),
DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a),
WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"),
DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"),
ValidationFailure { path: None, msg } => {
write!(f, "constructing invalid value: {}", msg)
}
@@ -190,11 +190,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
impl fmt::Display for AllocId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
// No "Display" since AllocIds are not usually user-visible.
#[derive(TyDecodable, TyEncodable)]
enum AllocDiscriminant {
@@ -470,7 +466,7 @@ fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>) -> AllocId {
return alloc_id;
}
let id = alloc_map.reserve();
debug!("creating alloc {:?} with id {}", alloc, id);
debug!("creating alloc {alloc:?} with id {id:?}");
alloc_map.alloc_map.insert(id, alloc.clone());
alloc_map.dedup.insert(alloc, id);
id
@@ -538,7 +534,7 @@ pub fn get_global_alloc(self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
match self.get_global_alloc(id) {
Some(alloc) => alloc,
None => bug!("could not find allocation for {}", id),
None => bug!("could not find allocation for {id:?}"),
}
}
@@ -546,7 +542,7 @@ pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
/// call this function twice, even with the same `Allocation` will ICE the compiler.
pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
}
}
@@ -144,7 +144,7 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
// Print offset only if it is non-zero.
if ptr.offset.bytes() > 0 {
write!(f, "+0x{:x}", ptr.offset.bytes())?;
write!(f, "+{:#x}", ptr.offset.bytes())?;
}
Ok(())
}
@@ -181,7 +181,7 @@ impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.provenance {
Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f),
None => write!(f, "0x{:x}", self.offset.bytes()),
None => write!(f, "{:#x}", self.offset.bytes()),
}
}
}
@@ -167,7 +167,7 @@ impl<Tag: Provenance> fmt::LowerHex for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr),
Scalar::Int(int) => write!(f, "0x{:x}", int),
Scalar::Int(int) => write!(f, "{:#x}", int),
}
}
}
+2 -2
View File
@@ -716,12 +716,12 @@ fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
}
write!(w, "{}", display_allocation(tcx, alloc.inner()))
};
write!(w, "\n{}", id)?;
write!(w, "\n{id:?}")?;
match tcx.get_global_alloc(id) {
// This can't really happen unless there are bugs, but it doesn't cost us anything to
// gracefully handle it and allow buggy rustc to be debugged via allocation printing.
None => write!(w, " (deallocated)")?,
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {})", inst)?,
Some(GlobalAlloc::Function(inst)) => write!(w, " (fn: {inst})")?,
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
@@ -452,6 +452,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl fmt::LowerHex for ScalarInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.check_data();
if f.alternate() {
// Like regular ints, alternate flag adds leading `0x`.
write!(f, "0x")?;
}
// Format as hex number wide enough to fit any value of the given `size`.
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
// Using a block `{self.data}` here to force a copy instead of using `self.data`
@@ -1495,6 +1495,15 @@ pub(crate) fn unresolved_macro_suggestions(
err.help("have you added the `#[macro_use]` on the module/import?");
return;
}
if ident.name == kw::Default
&& let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
&& let Some(span) = self.opt_span(def_id)
{
err.span_help(
self.session.source_map().guess_head_span(span),
"consider adding `#[derive(Default)]` to this enum",
);
}
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
ident,
@@ -1980,7 +1980,6 @@ fn maybe_report_ambiguity(
body_id,
span,
trait_ref.self_ty().skip_binder().into(),
vec![],
ErrorCode::E0282,
false,
)
@@ -2005,19 +2004,7 @@ fn maybe_report_ambiguity(
let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
let mut err = if let Some(subst) = subst {
let impl_candidates = self
.find_similar_impl_candidates(trait_ref)
.into_iter()
.map(|candidate| candidate.trait_ref)
.collect();
self.emit_inference_failure_err(
body_id,
span,
subst,
impl_candidates,
ErrorCode::E0283,
true,
)
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
} else {
struct_span_err!(
self.tcx.sess,
@@ -2117,7 +2104,7 @@ fn maybe_report_ambiguity(
return;
}
self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282, false)
self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, false)
}
ty::PredicateKind::Subtype(data) => {
@@ -2131,14 +2118,7 @@ fn maybe_report_ambiguity(
let SubtypePredicate { a_is_expected: _, a, b } = data;
// both must be type variables, or the other would've been instantiated
assert!(a.is_ty_var() && b.is_ty_var());
self.emit_inference_failure_err(
body_id,
span,
a.into(),
vec![],
ErrorCode::E0282,
true,
)
self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, true)
}
ty::PredicateKind::Projection(data) => {
if predicate.references_error() || self.is_tainted_by_errors() {
@@ -2155,7 +2135,6 @@ fn maybe_report_ambiguity(
body_id,
span,
subst,
vec![],
ErrorCode::E0284,
true,
);
@@ -1538,15 +1538,8 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
ty
} else {
if !self.is_tainted_by_errors() {
self.emit_inference_failure_err(
(**self).body_id,
sp,
ty.into(),
vec![],
E0282,
true,
)
.emit();
self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
.emit();
}
let err = self.tcx.ty_error();
self.demand_suptype(sp, err, ty);
@@ -692,7 +692,6 @@ fn report_type_error(&self, t: Ty<'tcx>) {
Some(self.body.id()),
self.span.to_span(self.tcx),
t.into(),
vec![],
E0282,
false,
)
@@ -707,7 +706,6 @@ fn report_const_error(&self, c: ty::Const<'tcx>) {
Some(self.body.id()),
self.span.to_span(self.tcx),
c.into(),
vec![],
E0282,
false,
)
+7
View File
@@ -7,6 +7,7 @@
use crate::fmt;
use crate::io::{self, IoSlice, IoSliceMut};
use crate::iter::FusedIterator;
use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
use crate::sys_common::net as net_imp;
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -1009,6 +1010,9 @@ fn next(&mut self) -> Option<io::Result<TcpStream>> {
}
}
#[stable(feature = "tcp_listener_incoming_fused_iterator", since = "1.64.0")]
impl FusedIterator for Incoming<'_> {}
#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
impl Iterator for IntoIncoming {
type Item = io::Result<TcpStream>;
@@ -1017,6 +1021,9 @@ fn next(&mut self) -> Option<io::Result<TcpStream>> {
}
}
#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
impl FusedIterator for IntoIncoming {}
impl AsInner<net_imp::TcpListener> for TcpListener {
fn as_inner(&self) -> &net_imp::TcpListener {
&self.0
@@ -0,0 +1,8 @@
pub enum Test { //~ HELP consider adding `#[derive(Default)]` to this enum
#[default]
//~^ ERROR cannot find attribute `default` in this scope
First,
Second,
}
fn main() {}
@@ -0,0 +1,14 @@
error: cannot find attribute `default` in this scope
--> $DIR/suggest-default-attribute.rs:2:7
|
LL | #[default]
| ^^^^^^^
|
help: consider adding `#[derive(Default)]` to this enum
--> $DIR/suggest-default-attribute.rs:1:1
|
LL | pub enum Test {
| ^^^^^^^^^^^^^
error: aborting due to previous error
@@ -2,7 +2,12 @@ error[E0282]: type annotations needed
--> $DIR/ambiguous_type_parameter.rs:16:19
|
LL | InMemoryStore.get_raw(&String::default());
| ^^^^^^^ cannot infer type for type parameter `K`
| ^^^^^^^
|
help: try using a fully qualified path to specify the expected types
|
LL | <InMemoryStore as Store<String, HashMap<K, String>>>::get_raw(&InMemoryStore, &String::default());
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~
error: aborting due to previous error
@@ -16,8 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> {
fn main() {
let x = || -> Result<_, QualifiedError<_>> {
//~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>`
infallible()?;
Ok(())
//~^ ERROR type annotations needed
};
}
@@ -1,16 +1,15 @@
error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>`
--> $DIR/cannot-infer-partial-try-return.rs:18:13
error[E0282]: type annotations needed
--> $DIR/cannot-infer-partial-try-return.rs:20:9
|
LL | let x = || -> Result<_, QualifiedError<_>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | infallible()?;
| ------------- type must be known at this point
LL | Ok(())
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
|
help: try giving this closure an explicit return type
help: consider specifying the generic arguments
|
LL | let x = || -> Result<(), QualifiedError<_>> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | Ok::<(), QualifiedError<_>>(())
| +++++++++++++++++++++++++
error: aborting due to previous error
@@ -0,0 +1,19 @@
// Test that we suggest specifying the generic argument of `channel`
// instead of the return type of that function, which is a lot more
// complex.
use std::sync::mpsc::channel;
fn no_tuple() {
let _data =
channel(); //~ ERROR type annotations needed
}
fn tuple() {
let (_sender, _receiver) =
channel(); //~ ERROR type annotations needed
}
fn main() {
no_tuple();
tuple();
}
@@ -0,0 +1,25 @@
error[E0282]: type annotations needed
--> $DIR/channel.rs:8:9
|
LL | channel();
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
|
help: consider specifying the generic argument
|
LL | channel::<T>();
| +++++
error[E0282]: type annotations needed
--> $DIR/channel.rs:13:9
|
LL | channel();
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel`
|
help: consider specifying the generic argument
|
LL | channel::<T>();
| +++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0282`.
+7 -2
View File
@@ -1,8 +1,13 @@
error[E0282]: type annotations needed
--> $DIR/issue-23041.rs:6:22
--> $DIR/issue-23041.rs:6:7
|
LL | b.downcast_ref::<fn(_)->_>();
| ^^^^^^^^ cannot infer type
| ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref`
|
help: consider specifying the generic arguments
|
LL | b.downcast_ref::<fn(_) -> _>();
| ~~~~~~~~~~~~~~
error: aborting due to previous error
+7 -2
View File
@@ -1,8 +1,13 @@
error[E0282]: type annotations needed
--> $DIR/issue-24013.rs:5:20
--> $DIR/issue-24013.rs:5:13
|
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ^^^^^^ cannot infer type
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap`
|
help: consider specifying the generic arguments
|
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ~~~~~~~~~~
error: aborting due to previous error
+2 -2
View File
@@ -5,10 +5,10 @@
struct Foo<T> {foo: PhantomData<T>}
fn main() {
let (tx, rx) = //~ ERROR type annotations needed
let (tx, rx) =
channel();
// FIXME(#89862): Suggest adding a generic argument to `channel` instead
spawn(move || {
tx.send(Foo{ foo: PhantomData });
//~^ ERROR type annotations needed
});
}
+7 -7
View File
@@ -1,13 +1,13 @@
error[E0282]: type annotations needed for `(Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`
--> $DIR/issue-25368.rs:8:9
error[E0282]: type annotations needed
--> $DIR/issue-25368.rs:11:27
|
LL | let (tx, rx) =
| ^^^^^^^^
LL | tx.send(Foo{ foo: PhantomData });
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData`
|
help: consider giving this pattern a type, where the type for type parameter `T` is specified
help: consider specifying the generic argument
|
LL | let (tx, rx): (Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>) =
| +++++++++++++++++++++++++++++++++++++++++++++++++++++
LL | tx.send(Foo{ foo: PhantomData::<T> });
| +++++
error: aborting due to previous error
@@ -13,7 +13,7 @@ error[E0283]: type annotations needed
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7
|
LL | x.foo();
| ^^^ cannot infer type for struct `Vec<_>`
| ^^^
|
note: multiple `impl`s satisfying `Vec<_>: Foo` found
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1
@@ -23,6 +23,10 @@ LL | impl Foo for Vec<usize> {
...
LL | impl Foo for Vec<isize> {
| ^^^^^^^^^^^^^^^^^^^^^^^
help: try using a fully qualified path to specify the expected types
|
LL | <Vec<T> as Foo>::foo(&x);
| ++++++++++++++++++++++ ~
error[E0308]: mismatched types
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20