1
Fork 0

Auto merge of #76912 - RalfJung:rollup-q9ur56h, r=RalfJung

Rollup of 14 pull requests

Successful merges:

 - #73963 (deny(unsafe_op_in_unsafe_fn) in libstd/path.rs)
 - #75099 (lint/ty: move fns to avoid abstraction violation)
 - #75502 (Use implicit (not explicit) rules for promotability by default in `const fn`)
 - #75580 (Add test for checking duplicated branch or-patterns)
 - #76310 (Add `[T; N]: TryFrom<Vec<T>>` (insta-stable))
 - #76400 (Clean up vec benches bench_in_place style)
 - #76434 (do not inline black_box when building for Miri)
 - #76492 (Add associated constant `BITS` to all integer types)
 - #76525 (Add as_str() to string::Drain.)
 - #76636 (assert ScalarMaybeUninit size)
 - #76749 (give *even better* suggestion when matching a const range)
 - #76757 (don't convert types to the same type with try_into (clippy::useless_conversion))
 - #76796 (Give a better error message when x.py uses the wrong stage for CI)
 - #76798 (Build fixes for RISC-V 32-bit Linux support)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-09-19 11:29:00 +00:00
commit 8e9d5db839
46 changed files with 456 additions and 181 deletions

View file

@ -14,6 +14,7 @@
#![feature(generators)]
#![feature(generator_trait)]
#![feature(fn_traits)]
#![feature(int_bits_const)]
#![feature(min_specialization)]
#![feature(optin_builtin_traits)]
#![feature(nll)]

View file

@ -48,7 +48,7 @@ where
P: Pointer,
T: Tag,
{
const TAG_BIT_SHIFT: usize = (8 * std::mem::size_of::<usize>()) - T::BITS;
const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
const ASSERTION: () = {
assert!(T::BITS <= P::BITS);
// Used for the transmute_copy's below

View file

@ -21,7 +21,8 @@
//! `late_lint_methods!` invocation in `lib.rs`.
use crate::{
types::CItemKind, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
types::{transparent_newtype_field, CItemKind},
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
};
use rustc_ast::attr::{self, HasAttrs};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
@ -2688,8 +2689,7 @@ impl ClashingExternDeclarations {
if is_transparent && !is_non_null {
debug_assert!(def.variants.len() == 1);
let v = &def.variants[VariantIdx::new(0)];
ty = v
.transparent_newtype_field(tcx)
ty = transparent_newtype_field(tcx, v)
.expect(
"single-variant transparent structure with zero-sized field",
)

View file

@ -639,6 +639,26 @@ crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtD
.any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed))
}
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// field.
pub fn transparent_newtype_field<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
variant: &'a ty::VariantDef,
) -> Option<&'a ty::FieldDef> {
let param_env = tcx.param_env(variant.def_id);
for field in &variant.fields {
let field_ty = tcx.type_of(field.did);
let is_zst =
tcx.layout_of(param_env.and(field_ty)).map(|layout| layout.is_zst()).unwrap_or(false);
if !is_zst {
return Some(field);
}
}
None
}
/// Is type known to be non-null?
crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
let tcx = cx.tcx;
@ -654,7 +674,7 @@ crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: C
}
for variant in &def.variants {
if let Some(field) = variant.transparent_newtype_field(tcx) {
if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
return true;
}
@ -675,7 +695,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
ty::Adt(field_def, field_substs) => {
let inner_field_ty = {
let first_non_zst_ty =
field_def.variants.iter().filter_map(|v| v.transparent_newtype_field(tcx));
field_def.variants.iter().filter_map(|v| transparent_newtype_field(cx.tcx, v));
debug_assert_eq!(
first_non_zst_ty.clone().count(),
1,
@ -816,7 +836,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if def.repr.transparent() {
// Can assume that only one field is not a ZST, so only check
// that field's type for FFI-safety.
if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) {
if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
self.check_field_type_for_ffi(cache, field, substs)
} else {
bug!("malformed transparent type");

View file

@ -578,6 +578,9 @@ pub enum ScalarMaybeUninit<Tag = ()> {
Uninit,
}
#[cfg(target_arch = "x86_64")]
static_assert_size!(ScalarMaybeUninit, 24);
impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
#[inline(always)]
fn from(s: Scalar<Tag>) -> Self {

View file

@ -1999,7 +1999,7 @@ pub struct VariantDef {
flags: VariantFlags,
}
impl<'tcx> VariantDef {
impl VariantDef {
/// Creates a new `VariantDef`.
///
/// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
@ -2065,19 +2065,6 @@ impl<'tcx> VariantDef {
pub fn is_recovered(&self) -> bool {
self.flags.intersects(VariantFlags::IS_RECOVERED)
}
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// field.
pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> {
for field in &self.fields {
let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id));
if !field_ty.is_zst(tcx, self.def_id) {
return Some(field);
}
}
None
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]

View file

@ -2322,9 +2322,4 @@ impl<'tcx> TyS<'tcx> {
}
}
}
/// Is this a zero-sized type?
pub fn is_zst(&'tcx self, tcx: TyCtxt<'tcx>, did: DefId) -> bool {
tcx.layout_of(tcx.param_env(did).and(self)).map(|layout| layout.is_zst()).unwrap_or(false)
}
}

View file

@ -4,7 +4,6 @@ use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use smallvec::{smallvec, SmallVec};
use std::convert::TryInto;
use std::mem;
use super::abs_domain::Lift;
@ -481,12 +480,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
};
let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
let len: u64 = match base_ty.kind() {
ty::Array(_, size) => {
let length = size.eval_usize(self.builder.tcx, self.builder.param_env);
length
.try_into()
.expect("slice pattern of array with more than u32::MAX elements")
}
ty::Array(_, size) => size.eval_usize(self.builder.tcx, self.builder.param_env),
_ => bug!("from_end: false slice pattern of non-array type"),
};
for offset in from..to {

View file

@ -551,7 +551,7 @@ where
let n = base.len(self)?;
if n < min_length {
// This can only be reached in ConstProp and non-rustc-MIR.
throw_ub!(BoundsCheckFailed { len: min_length.into(), index: n });
throw_ub!(BoundsCheckFailed { len: min_length, index: n });
}
let index = if from_end {
@ -565,9 +565,7 @@ where
self.mplace_index(base, index)?
}
Subslice { from, to, from_end } => {
self.mplace_subslice(base, u64::from(from), u64::from(to), from_end)?
}
Subslice { from, to, from_end } => self.mplace_subslice(base, from, to, from_end)?,
})
}

View file

@ -734,7 +734,14 @@ impl<'tcx> Validator<'_, 'tcx> {
) -> Result<(), Unpromotable> {
let fn_ty = callee.ty(self.body, self.tcx);
if !self.explicit && self.const_kind.is_none() {
// `const` and `static` use the explicit rules for promotion regardless of the `Candidate`,
// meaning calls to `const fn` can be promoted.
let context_uses_explicit_promotion_rules = matches!(
self.const_kind,
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
);
if !self.explicit && !context_uses_explicit_promotion_rules {
if let ty::FnDef(def_id, _) = *fn_ty.kind() {
// Never promote runtime `const fn` calls of
// functions without `#[rustc_promotable]`.

View file

@ -33,7 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.hir.tcx();
let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() {
ty::Array(_, length) => {
(length.eval_usize(tcx, self.hir.param_env).try_into().unwrap(), true)
(length.eval_usize(tcx, self.hir.param_env), true)
}
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
};

View file

@ -1,5 +1,6 @@
use crate::check::FnCtxt;
use rustc_ast as ast;
use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
@ -740,6 +741,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_ty
}
fn maybe_suggest_range_literal(
&self,
e: &mut DiagnosticBuilder<'_>,
opt_def_id: Option<hir::def_id::DefId>,
ident: Ident,
) -> bool {
match opt_def_id {
Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Const(_, body_id), ..
})) => match self.tcx.hir().get(body_id.hir_id) {
hir::Node::Expr(expr) => {
if hir::is_range_literal(expr) {
let span = self.tcx.hir().span(body_id.hir_id);
if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
e.span_suggestion_verbose(
ident.span,
"you may want to move the range into the match block",
snip,
Applicability::MachineApplicable,
);
return true;
}
}
}
_ => (),
},
_ => (),
},
_ => (),
}
false
}
fn emit_bad_pat_path(
&self,
mut e: DiagnosticBuilder<'_>,
@ -772,12 +807,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
_ => {
let const_def_id = match pat_ty.kind() {
let (type_def_id, item_def_id) = match pat_ty.kind() {
Adt(def, _) => match res {
Res::Def(DefKind::Const, _) => Some(def.did),
_ => None,
Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)),
_ => (None, None),
},
_ => None,
_ => (None, None),
};
let ranges = &[
@ -788,11 +823,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.lang_items().range_inclusive_struct(),
self.tcx.lang_items().range_to_inclusive_struct(),
];
if const_def_id != None && ranges.contains(&const_def_id) {
let msg = "constants only support matching by type, \
if you meant to match against a range of values, \
consider using a range pattern like `min ..= max` in the match block";
e.note(msg);
if type_def_id != None && ranges.contains(&type_def_id) {
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
let msg = "constants only support matching by type, \
if you meant to match against a range of values, \
consider using a range pattern like `min ..= max` in the match block";
e.note(msg);
}
} else {
let msg = "introduce a new binding instead";
let sugg = format!("other_{}", ident.as_str().to_lowercase());