Skip to content

Rollup of 3 pull requests #57938

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2722,6 +2722,7 @@ dependencies = [
"rustc_errors 0.0.0",
"rustc_mir 0.0.0",
"syntax 0.0.0",
"syntax_ext 0.0.0",
"syntax_pos 0.0.0",
]

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ impl_stable_hash_for!(struct ty::FieldDef {
impl_stable_hash_for!(
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
Scalar(val),
ScalarPair(a, b),
Slice(a, b),
ByRef(id, alloc, offset),
}
);
Expand Down
83 changes: 50 additions & 33 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ use ty::query::{Providers, queries};
use lint;
use errors::Applicability;
use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
use rustc_data_structures::fx::FxHashMap;

use std::collections::VecDeque;
use std::{fmt, u32};
Expand Down Expand Up @@ -1446,7 +1447,7 @@ fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local)
None => {
this.pat_bindings(&local.pat, |this, ln, var, sp, id| {
let span = local.pat.simple_ident().map_or(sp, |ident| ident.span);
this.warn_about_unused(span, id, ln, var);
this.warn_about_unused(vec![span], id, ln, var);
})
}
}
Expand All @@ -1455,12 +1456,29 @@ fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local)
}

fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) {
// only consider the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be
// the "authoritative" set of ids
this.arm_pats_bindings(arm.pats.first().map(|p| &**p), |this, ln, var, sp, id| {
this.warn_about_unused(sp, id, ln, var);
});
// Only consider the variable from the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be the "authoritative" set of
// ids. However, we should take the spans of variables with the same name from the later
// patterns so the suggestions to prefix with underscores will apply to those too.
let mut vars: FxHashMap<String, (LiveNode, Variable, HirId, Vec<Span>)> = Default::default();

for pat in &arm.pats {
this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| {
let name = this.ir.variable_name(var);
vars.entry(name)
.and_modify(|(.., spans)| {
spans.push(sp);
})
.or_insert_with(|| {
(ln, var, id, vec![sp])
});
});
}

for (_, (ln, var, id, spans)) in vars {
this.warn_about_unused(spans, id, ln, var);
}

intravisit::walk_arm(this, arm);
}

Expand Down Expand Up @@ -1551,7 +1569,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let var = self.variable(hir_id, sp);
// Ignore unused self.
if ident.name != keywords::SelfLower.name() {
if !self.warn_about_unused(sp, hir_id, entry_ln, var) {
if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) {
if self.live_on_entry(entry_ln, var).is_none() {
self.report_dead_assign(hir_id, sp, var, true);
}
Expand All @@ -1563,14 +1581,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) {
self.pat_bindings(pat, |this, ln, var, sp, id| {
if !this.warn_about_unused(sp, id, ln, var) {
if !this.warn_about_unused(vec![sp], id, ln, var) {
this.warn_about_dead_assign(sp, id, ln, var);
}
})
}

fn warn_about_unused(&self,
sp: Span,
spans: Vec<Span>,
hir_id: HirId,
ln: LiveNode,
var: Variable)
Expand All @@ -1587,33 +1605,36 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.assigned_on_exit(ln, var).is_some()
};

let suggest_underscore_msg = format!("consider using `_{}` instead", name);

if is_assigned {
self.ir.tcx
.lint_hir_note(lint::builtin::UNUSED_VARIABLES, hir_id, sp,
&format!("variable `{}` is assigned to, but never used",
name),
&suggest_underscore_msg);
self.ir.tcx.lint_hir_note(
lint::builtin::UNUSED_VARIABLES,
hir_id,
spans.clone(),
&format!("variable `{}` is assigned to, but never used", name),
&format!("consider using `_{}` instead", name),
);
} else if name != "self" {
let msg = format!("unused variable: `{}`", name);
let mut err = self.ir.tcx
.struct_span_lint_hir(lint::builtin::UNUSED_VARIABLES, hir_id, sp, &msg);
let mut err = self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_VARIABLES,
hir_id,
spans.clone(),
&format!("unused variable: `{}`", name),
);

if self.ir.variable_is_shorthand(var) {
err.span_suggestion(
sp,
err.multipart_suggestion(
"try ignoring the field",
format!("{}: _", name),
Applicability::MachineApplicable,
spans.iter().map(|span| (*span, format!("{}: _", name))).collect(),
Applicability::MachineApplicable
);
} else {
err.span_suggestion_short(
sp,
&suggest_underscore_msg,
format!("_{}", name),
err.multipart_suggestion(
"consider prefixing with an underscore",
spans.iter().map(|span| (*span, format!("_{}", name))).collect(),
Applicability::MachineApplicable,
);
}

err.emit()
}
}
Expand All @@ -1623,11 +1644,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
}

fn warn_about_dead_assign(&self,
sp: Span,
hir_id: HirId,
ln: LiveNode,
var: Variable) {
fn warn_about_dead_assign(&self, sp: Span, hir_id: HirId, ln: LiveNode, var: Variable) {
if self.live_on_exit(ln, var).is_none() {
self.report_dead_assign(hir_id, sp, var, false);
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/mir/interpret/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub struct Pointer<Tag=(),Id=AllocId> {
pub tag: Tag,
}

static_assert!(POINTER_SIZE: ::std::mem::size_of::<Pointer>() == 16);

/// Produces a `Pointer` which points to the beginning of the Allocation
impl From<AllocId> for Pointer {
#[inline(always)]
Expand Down
28 changes: 14 additions & 14 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,28 @@ pub enum ConstValue<'tcx> {
/// Not using the enum `Value` to encode that this must not be `Undef`
Scalar(Scalar),

/// Used only for *fat pointers* with layout::abi::ScalarPair
/// Used only for slices and strings (`&[T]`, `&str`, `*const [T]`, `*mut str`, `Box<str>`, ...)
///
/// Needed for pattern matching code related to slices and strings.
ScalarPair(Scalar, Scalar),
/// Empty slices don't necessarily have an address backed by an `AllocId`, thus we also need to
/// enable integer pointers. The `Scalar` type covers exactly those two cases. While we could
/// create dummy-`AllocId`s, the additional code effort for the conversions doesn't seem worth
/// it.
Slice(Scalar, u64),

/// An allocation + offset into the allocation.
/// Invariant: The AllocId matches the allocation.
ByRef(AllocId, &'tcx Allocation, Size),
}

#[cfg(target_arch = "x86_64")]
static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 40);

impl<'tcx> ConstValue<'tcx> {
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar> {
match *self {
ConstValue::ByRef(..) |
ConstValue::ScalarPair(..) => None,
ConstValue::Slice(..) => None,
ConstValue::Scalar(val) => Some(val),
}
}
Expand All @@ -56,17 +62,8 @@ impl<'tcx> ConstValue<'tcx> {
pub fn new_slice(
val: Scalar,
len: u64,
cx: &impl HasDataLayout
) -> Self {
ConstValue::ScalarPair(val, Scalar::Bits {
bits: len as u128,
size: cx.data_layout().pointer_size.bytes() as u8,
})
}

#[inline]
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
ConstValue::ScalarPair(val, Scalar::Ptr(vtable))
ConstValue::Slice(val, len)
}
}

Expand All @@ -90,6 +87,9 @@ pub enum Scalar<Tag=(), Id=AllocId> {
Ptr(Pointer<Tag, Id>),
}

#[cfg(target_arch = "x86_64")]
static_assert!(SCALAR_SIZE: ::std::mem::size_of::<Scalar>() == 24);

impl<Tag> fmt::Display for Scalar<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expand Down
30 changes: 14 additions & 16 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2702,23 +2702,21 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
return write!(f, "{}", item_path_str(did));
}
// print string literals
if let ConstValue::ScalarPair(ptr, len) = value {
if let ConstValue::Slice(ptr, len) = value {
if let Scalar::Ptr(ptr) = ptr {
if let Scalar::Bits { bits: len, .. } = len {
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
return ty::tls::with(|tcx| {
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
assert_eq!(len as usize as u128, len);
let slice =
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
write!(f, "{:?}", s)
} else {
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
}
});
}
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
return ty::tls::with(|tcx| {
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
assert_eq!(len as usize as u64, len);
let slice =
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
write!(f, "{:?}", s)
} else {
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
}
});
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,7 @@ macro_rules! nop_list_lift {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
type Lifted = &'tcx List<$lifted>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
if self.is_empty() {
if self.is_empty() {
return Some(List::empty());
}
if tcx.interners.arena.in_arena(*self as *const _) {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
match *self {
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
ConstValue::ScalarPair(x, y) => Some(ConstValue::ScalarPair(x, y)),
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
ConstValue::ByRef(x, alloc, z) => Some(ConstValue::ByRef(
x, alloc.lift_to_tcx(tcx)?, z,
)),
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,9 @@ pub enum LazyConst<'tcx> {
Evaluated(Const<'tcx>),
}

#[cfg(target_arch = "x86_64")]
static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);

impl<'tcx> LazyConst<'tcx> {
pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
match self {
Expand All @@ -2089,6 +2092,9 @@ pub struct Const<'tcx> {
pub val: ConstValue<'tcx>,
}

#[cfg(target_arch = "x86_64")]
static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 48);

impl<'tcx> Const<'tcx> {
#[inline]
pub fn from_scalar(
Expand Down
12 changes: 4 additions & 8 deletions src/librustc_codegen_ssa/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,17 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
);
OperandValue::Immediate(llval)
},
ConstValue::ScalarPair(a, b) => {
let (a_scalar, b_scalar) = match layout.abi {
layout::Abi::ScalarPair(ref a, ref b) => (a, b),
ConstValue::Slice(a, b) => {
let a_scalar = match layout.abi {
layout::Abi::ScalarPair(ref a, _) => a,
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
};
let a_llval = bx.cx().scalar_to_backend(
a,
a_scalar,
bx.cx().scalar_pair_element_backend_type(layout, 0, true),
);
let b_llval = bx.cx().scalar_to_backend(
b,
b_scalar,
bx.cx().scalar_pair_element_backend_type(layout, 1, true),
);
let b_llval = bx.cx().const_usize(b);
OperandValue::Pair(a_llval, b_llval)
},
ConstValue::ByRef(_, alloc, offset) => {
Expand Down
31 changes: 17 additions & 14 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,10 @@ where
krate = ReplaceBodyWithLoop::new(sess).fold_crate(krate);
}

let (has_proc_macro_decls, has_global_allocator) = time(sess, "AST validation", || {
ast_validation::check_crate(sess, &krate)
});

// If we're in rustdoc we're always compiling as an rlib, but that'll trip a
// bunch of checks in the `modify` function below. For now just skip this
// step entirely if we're rustdoc as it's not too useful anyway.
Expand All @@ -1031,23 +1035,26 @@ where
&mut resolver,
krate,
is_proc_macro_crate,
has_proc_macro_decls,
is_test_crate,
num_crate_types,
sess.diagnostic(),
)
});
}

// Expand global allocators, which are treated as an in-tree proc macro
krate = time(sess, "creating allocators", || {
allocator::expand::modify(
&sess.parse_sess,
&mut resolver,
krate,
crate_name.to_string(),
sess.diagnostic(),
)
});
if has_global_allocator {
// Expand global allocators, which are treated as an in-tree proc macro
krate = time(sess, "creating allocators", || {
allocator::expand::modify(
&sess.parse_sess,
&mut resolver,
krate,
crate_name.to_string(),
sess.diagnostic(),
)
});
}

// Done with macro expansion!

Expand All @@ -1065,10 +1072,6 @@ where
println!("{}", json::as_json(&krate));
}

time(sess, "AST validation", || {
ast_validation::check_crate(sess, &krate)
});

time(sess, "name resolution", || {
resolver.resolve_crate(&krate);
});
Expand Down
Loading