Auto merge of #74073 - Manishearth:rollup-faqo9lx, r=Manishearth

Rollup of 12 pull requests

Successful merges:

 - #72688 (added .collect() into String from Box<str>)
 - #73787 (Add unstable docs for rustc_attrs)
 - #73834 (Some refactoring around intrinsic type checking)
 - #73871 (Fix try_print_visible_def_path for Rust 2018)
 - #73937 (Explain exhaustive matching on {usize,isize} maximum values)
 - #73973 (Use `Span`s to identify unreachable subpatterns in or-patterns)
 - #74000 (add `lazy_normalization_consts` feature gate)
 - #74025 (Remove unnecessary release from Arc::try_unwrap)
 - #74027 (Convert more `DefId`s to `LocalDefId`s)
 - #74055 (Fix spacing in Iterator fold doc)
 - #74057 (expected_found `&T` -> `T`)
 - #74064 (variant_count: avoid incorrect dummy implementation)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-07-05 23:08:08 +00:00
commit 0c03aee8b8
56 changed files with 798 additions and 334 deletions

View file

@ -0,0 +1,53 @@
# `rustc_attrs`
This feature has no tracking issue, and is therefore internal to
the compiler, not being intended for general use.
Note: `rustc_attrs` enables many rustc-internal attributes and this page
only discuss a few of them.
------------------------
The `rustc_attrs` feature allows debugging rustc type layouts by using
`#[rustc_layout(...)]` to debug layout at compile time (it even works
with `cargo check`) as an alternative to `rustc -Z print-type-sizes`
that is way more verbose.
Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `abi`.
Note that it only work best with sized type without generics.
## Examples
```rust,ignore
#![feature(rustc_attrs)]
#[rustc_layout(abi, size)]
pub enum X {
Y(u8, u8, u8),
Z(isize),
}
```
When that is compiled, the compiler will error with something like
```text
error: abi: Aggregate { sized: true }
--> src/lib.rs:4:1
|
4 | / pub enum T {
5 | | Y(u8, u8, u8),
6 | | Z(isize),
7 | | }
| |_^
error: size: Size { raw: 16 }
--> src/lib.rs:4:1
|
4 | / pub enum T {
5 | | Y(u8, u8, u8),
6 | | Z(isize),
7 | | }
| |_^
error: aborting due to 2 previous errors
```

View file

@ -1774,6 +1774,15 @@ fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String {
}
}
#[stable(feature = "box_str2", since = "1.45.0")]
impl FromIterator<Box<str>> for String {
fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> String {
let mut buf = String::new();
buf.extend(iter);
buf
}
}
#[stable(feature = "herd_cows", since = "1.19.0")]
impl<'a> FromIterator<Cow<'a, str>> for String {
fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
@ -1842,6 +1851,13 @@ fn extend_one(&mut self, s: &'a str) {
}
}
#[stable(feature = "box_str2", since = "1.45.0")]
impl Extend<Box<str>> for String {
fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
iter.into_iter().for_each(move |s| self.push_str(&s));
}
}
#[stable(feature = "extend_string", since = "1.4.0")]
impl Extend<String> for String {
fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {

View file

@ -419,8 +419,7 @@ pub fn pin(data: T) -> Pin<Arc<T>> {
#[inline]
#[stable(feature = "arc_unique", since = "1.4.0")]
pub fn try_unwrap(this: Self) -> Result<T, Self> {
// See `drop` for why all these atomics are like this
if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() {
if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() {
return Err(this);
}

View file

@ -2004,12 +2004,6 @@ pub fn coverage_counter_subtract(
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
}
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
#[cfg(bootstrap)]
pub const fn variant_count<T>() -> usize {
0
}
// Some functions are defined here because they accidentally got made
// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
// (`transmute` also falls into this category, but it cannot be wrapped due to the

View file

@ -1521,7 +1521,7 @@ fn inspect<F>(self, f: F) -> Inspect<Self, F>
///
/// let iter = a.iter();
///
/// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i );
/// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i);
///
/// assert_eq!(sum, 6);
///
@ -1535,7 +1535,7 @@ fn inspect<F>(self, f: F) -> Inspect<Self, F>
/// let mut iter = a.iter();
///
/// // instead, we add in a .by_ref()
/// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i );
/// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i);
///
/// assert_eq!(sum, 3);
///

View file

@ -125,7 +125,7 @@
#![feature(unsized_locals)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(variant_count)]
#![cfg_attr(not(bootstrap), feature(variant_count))]
#![feature(doc_alias)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]

View file

@ -1037,6 +1037,7 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
/// assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
/// ```
#[inline(always)]
#[cfg(not(bootstrap))]
#[unstable(feature = "variant_count", issue = "73662")]
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
pub const fn variant_count<T>() -> usize {

View file

@ -570,6 +570,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
/// Allows capturing variables in scope using format_args!
(active, format_args_capture, "1.46.0", Some(67984), None),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(active, lazy_normalization_consts, "1.46.0", Some(72219), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
@ -586,5 +589,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
sym::raw_dylib,
sym::const_trait_impl,
sym::const_trait_bound_opt_out,
sym::lazy_normalization_consts,
sym::specialization,
];

View file

@ -112,7 +112,7 @@ pub fn super_combine_tys<R>(
// All other cases of inference are errors
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
}
_ => ty::relate::super_relate_tys(relation, a, b),
@ -701,7 +701,7 @@ pub fn const_unification_error<'tcx>(
a_is_expected: bool,
(a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>),
) -> TypeError<'tcx> {
TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
}
fn int_unification_error<'tcx>(
@ -709,7 +709,7 @@ fn int_unification_error<'tcx>(
v: (ty::IntVarValue, ty::IntVarValue),
) -> TypeError<'tcx> {
let (a, b) = v;
TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
}
fn float_unification_error<'tcx>(
@ -717,5 +717,5 @@ fn float_unification_error<'tcx>(
v: (ty::FloatVarValue, ty::FloatVarValue),
) -> TypeError<'tcx> {
let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
}

View file

@ -1370,7 +1370,7 @@ pub fn borrowck_mode(self) -> BorrowckMode {
/// we still evaluate them eagerly.
#[inline]
pub fn lazy_normalization(self) -> bool {
self.features().const_generics
self.features().const_generics || self.features().lazy_normalization_consts
}
#[inline]

View file

@ -282,26 +282,27 @@ fn try_print_visible_def_path_recur(
// where there is no explicit `extern crate`, we just prepend
// the crate name.
match self.tcx().extern_crate(def_id) {
Some(&ExternCrate {
src: ExternCrateSource::Extern(def_id),
dependency_of: LOCAL_CRATE,
span,
..
}) => {
debug!("try_print_visible_def_path: def_id={:?}", def_id);
return Ok((
if !span.is_dummy() {
self.print_def_path(def_id, &[])?
} else {
self.path_crate(cnum)?
},
true,
));
}
Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
(ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
debug!("try_print_visible_def_path: def_id={:?}", def_id);
return Ok((
if !span.is_dummy() {
self.print_def_path(def_id, &[])?
} else {
self.path_crate(cnum)?
},
true,
));
}
(ExternCrateSource::Path, LOCAL_CRATE) => {
debug!("try_print_visible_def_path: def_id={:?}", def_id);
return Ok((self.path_crate(cnum)?, true));
}
_ => {}
},
None => {
return Ok((self.path_crate(cnum)?, true));
}
_ => {}
}
}

View file

@ -159,8 +159,8 @@ fn relate<R: TypeRelation<'tcx>>(
if a.c_variadic != b.c_variadic {
return Err(TypeError::VariadicMismatch(expected_found(
relation,
&a.c_variadic,
&b.c_variadic,
a.c_variadic,
b.c_variadic,
)));
}
let unsafety = relation.relate(a.unsafety, b.unsafety)?;
@ -200,7 +200,7 @@ fn relate<R: TypeRelation<'tcx>>(
b: ast::Unsafety,
) -> RelateResult<'tcx, ast::Unsafety> {
if a != b {
Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b)))
Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
} else {
Ok(a)
}
@ -213,7 +213,7 @@ fn relate<R: TypeRelation<'tcx>>(
a: abi::Abi,
b: abi::Abi,
) -> RelateResult<'tcx, abi::Abi> {
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) }
if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
}
}
@ -226,8 +226,8 @@ fn relate<R: TypeRelation<'tcx>>(
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(expected_found(
relation,
&a.item_def_id,
&b.item_def_id,
a.item_def_id,
b.item_def_id,
)))
} else {
let substs = relation.relate(a.substs, b.substs)?;
@ -245,8 +245,8 @@ fn relate<R: TypeRelation<'tcx>>(
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(expected_found(
relation,
&a.item_def_id,
&b.item_def_id,
a.item_def_id,
b.item_def_id,
)))
} else {
let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
@ -264,7 +264,7 @@ fn relate<R: TypeRelation<'tcx>>(
) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs })
@ -280,7 +280,7 @@ fn relate<R: TypeRelation<'tcx>>(
) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
// Different traits cannot be related.
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, None, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
@ -305,6 +305,7 @@ fn relate<R: TypeRelation<'tcx>>(
}
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
#[inline]
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Ty<'tcx>,
@ -421,7 +422,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize(
expected_found(relation, &sz_a_val, &sz_b_val),
expected_found(relation, sz_a_val, sz_b_val),
)),
_ => Err(err),
}
@ -440,9 +441,9 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
)?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len())))
Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
} else {
Err(TypeError::Sorts(expected_found(relation, &a, &b)))
Err(TypeError::Sorts(expected_found(relation, a, b)))
}
}
@ -471,7 +472,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
Ok(tcx.mk_opaque(a_def_id, substs))
}
_ => Err(TypeError::Sorts(expected_found(relation, &a, &b))),
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
}
}
@ -521,10 +522,10 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
if a_instance == b_instance {
Ok(ConstValue::Scalar(a_val))
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
}
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
}
}
@ -534,7 +535,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
if a_bytes == b_bytes {
Ok(a_val)
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
}
}
@ -554,7 +555,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
Ok(a_val)
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
}
}
// FIXME(const_generics): There are probably some `TyKind`s
@ -564,12 +565,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
DUMMY_SP,
&format!("unexpected consts: a: {:?}, b: {:?}", a, b),
);
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
}
}
}
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
_ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
};
new_val.map(ty::ConstKind::Value)
@ -584,7 +585,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
}
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
_ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
};
new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
}
@ -607,7 +608,7 @@ fn relate<R: TypeRelation<'tcx>>(
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
b_v.dedup();
if a_v.len() != b_v.len() {
return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b)));
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
}
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
@ -616,7 +617,7 @@ fn relate<R: TypeRelation<'tcx>>(
(Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
(Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))),
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
}
});
Ok(tcx.mk_existential_predicates(v)?)
@ -740,20 +741,14 @@ fn relate<R: TypeRelation<'tcx>>(
///////////////////////////////////////////////////////////////////////////
// Error handling
pub fn expected_found<R, T>(relation: &mut R, a: &T, b: &T) -> ExpectedFound<T>
pub fn expected_found<R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T>
where
R: TypeRelation<'tcx>,
T: Clone,
{
expected_found_bool(relation.a_is_expected(), a, b)
}
pub fn expected_found_bool<T>(a_is_expected: bool, a: &T, b: &T) -> ExpectedFound<T>
where
T: Clone,
{
let a = a.clone();
let b = b.clone();
pub fn expected_found_bool<T>(a_is_expected: bool, a: T, b: T) -> ExpectedFound<T> {
if a_is_expected {
ExpectedFound { expected: a, found: b }
} else {

View file

@ -122,7 +122,7 @@ pub(super) fn equate_inputs_and_outputs(
if let Err(terr) = self.eq_opaque_type_and_type(
mir_output_ty,
normalized_output_ty,
self.mir_def_id.to_def_id(),
self.mir_def_id,
Locations::All(output_span),
ConstraintCategory::BoringNoLocation,
) {
@ -145,7 +145,7 @@ pub(super) fn equate_inputs_and_outputs(
if let Err(err) = self.eq_opaque_type_and_type(
mir_output_ty,
user_provided_output_ty,
self.mir_def_id.to_def_id(),
self.mir_def_id,
Locations::All(output_span),
ConstraintCategory::BoringNoLocation,
) {

View file

@ -1144,7 +1144,8 @@ fn sub_types_or_anon(
// When you have `let x: impl Foo = ...` in a closure,
// the resulting inferend values are stored with the
// def-id of the base function.
let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id.to_def_id());
let parent_def_id =
self.tcx().closure_base_def_id(self.mir_def_id.to_def_id()).expect_local();
return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
} else {
return Err(terr);
@ -1208,7 +1209,7 @@ fn eq_opaque_type_and_type(
&mut self,
revealed_ty: Ty<'tcx>,
anon_ty: Ty<'tcx>,
anon_owner_def_id: DefId,
anon_owner_def_id: LocalDefId,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
@ -1238,8 +1239,7 @@ fn eq_opaque_type_and_type(
let tcx = infcx.tcx;
let param_env = self.param_env;
let body = self.body;
let concrete_opaque_types =
&tcx.typeck_tables_of(anon_owner_def_id.expect_local()).concrete_opaque_types;
let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types;
let mut opaque_type_values = Vec::new();
debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);

View file

@ -334,9 +334,9 @@ pub fn const_eval_raw_provider<'tcx>(
}
v
} else if def_id.is_local() {
} else if let Some(def_id) = def_id.as_local() {
// constant defined in this crate, we can figure out a lint level!
match tcx.def_kind(def_id) {
match tcx.def_kind(def_id.to_def_id()) {
// constants never produce a hard error at the definition site. Anything else is
// a backwards compatibility hazard (and will break old versions of winapi for
// sure)
@ -346,7 +346,7 @@ pub fn const_eval_raw_provider<'tcx>(
// validation thus preventing such a hard error from being a backwards
// compatibility hazard
DefKind::Const | DefKind::AssocConst => {
let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
let hir_id = tcx.hir().as_local_hir_id(def_id);
err.report_as_lint(
tcx.at(tcx.def_span(def_id)),
"any use of this value will cause an error",
@ -369,7 +369,7 @@ pub fn const_eval_raw_provider<'tcx>(
err.report_as_lint(
tcx.at(span),
"reaching this expression at runtime will panic or abort",
tcx.hir().as_local_hir_id(def_id.expect_local()),
tcx.hir().as_local_hir_id(def_id),
Some(err.span),
)
}

View file

@ -22,7 +22,7 @@
pub struct ConstCx<'mir, 'tcx> {
pub body: &'mir mir::Body<'tcx>,
pub tcx: TyCtxt<'tcx>,
pub def_id: DefId,
pub def_id: LocalDefId,
pub param_env: ty::ParamEnv<'tcx>,
pub const_kind: Option<hir::ConstContext>,
}
@ -40,7 +40,7 @@ pub fn new_with_param_env(
param_env: ty::ParamEnv<'tcx>,
) -> Self {
let const_kind = tcx.hir().body_const_context(def_id);
ConstCx { body, tcx, def_id: def_id.to_def_id(), param_env, const_kind }
ConstCx { body, tcx, def_id: def_id, param_env, const_kind }
}
/// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).

View file

@ -29,13 +29,7 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<
return;
}
let ccx = ConstCx {
body,
tcx,
def_id: def_id.to_def_id(),
const_kind,
param_env: tcx.param_env(def_id),
};
let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };

View file

@ -126,7 +126,7 @@ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
// because that component may be part of an enum variant (e.g.,
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
// structural-match (`Option::None`).
let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap());
let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id);
traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some()
}

View file

@ -56,7 +56,7 @@ pub fn indirectly_mutable(
// without breaking stable code?
MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
.unsound_ignore_borrow_on_drop()
.into_engine(tcx, &body, def_id)
.into_engine(tcx, &body, def_id.to_def_id())
.iterate_to_fixpoint()
.into_results_cursor(&body)
});
@ -83,7 +83,7 @@ pub fn needs_drop(
let ConstCx { tcx, body, def_id, .. } = *ccx;
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
.into_engine(tcx, &body, def_id)
.into_engine(tcx, &body, def_id.to_def_id())
.iterate_to_fixpoint()
.into_results_cursor(&body)
});
@ -110,7 +110,7 @@ pub fn has_mut_interior(
let ConstCx { tcx, body, def_id, .. } = *ccx;
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
.into_engine(tcx, &body, def_id)
.into_engine(tcx, &body, def_id.to_def_id())
.iterate_to_fixpoint()
.into_results_cursor(&body)
});
@ -153,7 +153,7 @@ fn in_return_place(&mut self, ccx: &'mir ConstCx<'mir, 'tcx>) -> ConstQualifs {
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
.into_engine(ccx.tcx, &ccx.body, ccx.def_id)
.into_engine(ccx.tcx, &ccx.body, ccx.def_id.to_def_id())
.iterate_to_fixpoint()
.into_results_cursor(&ccx.body);
@ -195,13 +195,13 @@ pub fn check_body(&mut self) {
let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn)
&& crate::const_eval::is_min_const_fn(tcx, def_id))
&& crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id()))
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
if use_min_const_fn_checks {
// Enforce `min_const_fn` for stable `const fn`s.
use crate::transform::qualify_min_const_fn::is_min_const_fn;
if let Err((span, err)) = is_min_const_fn(tcx, def_id, &body) {
if let Err((span, err)) = is_min_const_fn(tcx, def_id.to_def_id(), &body) {
error_min_const_fn_violation(tcx, span, err);
return;
}
@ -212,10 +212,10 @@ pub fn check_body(&mut self) {
// Ensure that the end result is `Sync` in a non-thread local `static`.
let should_check_for_sync = const_kind
== Some(hir::ConstContext::Static(hir::Mutability::Not))
&& !tcx.is_thread_local_static(def_id);
&& !tcx.is_thread_local_static(def_id.to_def_id());
if should_check_for_sync {
let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
let hir_id = tcx.hir().as_local_hir_id(def_id);
check_return_ty_is_sync(tcx, &body, hir_id);
}
}
@ -535,7 +535,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
// `#[allow_internal_unstable]`.
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
if !self.span.allows_unstable(feature)
&& !lib_feature_allowed(self.tcx, self.def_id, feature)
&& !lib_feature_allowed(self.tcx, self.def_id.to_def_id(), feature)
{
self.check_op(ops::FnCallUnstable(def_id, feature));
}

View file

@ -203,7 +203,8 @@ pub fn run_passes(
}
fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
let const_kind = tcx.hir().body_const_context(def_id.expect_local());
let def_id = def_id.expect_local();
let const_kind = tcx.hir().body_const_context(def_id);
// No need to const-check a non-const `fn`.
if const_kind.is_none() {
@ -214,7 +215,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
// cannot yet be stolen), because `mir_validated()`, which steals
// from `mir_const(), forces this query to execute before
// performing the steal.
let body = &tcx.mir_const(def_id).borrow();
let body = &tcx.mir_const(def_id.to_def_id()).borrow();
if body.return_ty().references_error() {
tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors");

View file

@ -60,15 +60,16 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
return;
}
let def_id = src.def_id();
let def_id = src.def_id().expect_local();
let mut rpo = traversal::reverse_postorder(body);
let ccx = ConstCx::new(tcx, def_id.expect_local(), body);
let ccx = ConstCx::new(tcx, def_id, body);
let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo);
let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates);
let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates);
let promoted =
promote_candidates(def_id.to_def_id(), body, tcx, temps, promotable_candidates);
self.promoted_fragments.set(promoted);
}
}
@ -724,7 +725,7 @@ fn validate_call(
ty::FnDef(def_id, _) => {
is_const_fn(self.tcx, def_id)
|| is_unstable_const_fn(self.tcx, def_id).is_some()
|| is_lang_panic_fn(self.tcx, self.def_id)
|| is_lang_panic_fn(self.tcx, self.def_id.to_def_id())
}
_ => false,
};

View file

@ -276,6 +276,7 @@
use self::WitnessPreference::*;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::vec::Idx;
use super::{compare_const_vals, PatternFoldable, PatternFolder};
@ -1246,15 +1247,15 @@ fn push_on_patstack(self, stack: &[&'p Pat<'tcx>]) -> PatStack<'p, 'tcx> {
}
#[derive(Clone, Debug)]
crate enum Usefulness<'tcx, 'p> {
crate enum Usefulness<'tcx> {
/// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
Useful(Vec<&'p Pat<'tcx>>),
Useful(Vec<Span>),
/// Carries a list of witnesses of non-exhaustiveness.
UsefulWithWitness(Vec<Witness<'tcx>>),
NotUseful,
}
impl<'tcx, 'p> Usefulness<'tcx, 'p> {
impl<'tcx> Usefulness<'tcx> {
fn new_useful(preference: WitnessPreference) -> Self {
match preference {
ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
@ -1269,7 +1270,7 @@ fn is_useful(&self) -> bool {
}
}
fn apply_constructor(
fn apply_constructor<'p>(
self,
cx: &MatchCheckCtxt<'p, 'tcx>,
ctor: &Constructor<'tcx>,
@ -1828,7 +1829,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
hir_id: HirId,
is_under_guard: bool,
is_top_level: bool,
) -> Usefulness<'tcx, 'p> {
) -> Usefulness<'tcx> {
let &Matrix(ref rows) = matrix;
debug!("is_useful({:#?}, {:#?})", matrix, v);
@ -1852,16 +1853,35 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// We need to push the already-seen patterns into the matrix in order to detect redundant
// branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
let mut matrix = matrix.clone();
let mut unreachable_pats = Vec::new();
// `Vec` of all the unreachable branches of the current or-pattern.
let mut unreachable_branches = Vec::new();
// Subpatterns that are unreachable from all branches. E.g. in the following case, the last
// `true` is unreachable only from one branch, so it is overall reachable.
// ```
// match (true, true) {
// (true, true) => {}
// (false | true, false | true) => {}
// }
// ```
let mut unreachable_subpats = FxHashSet::default();
// Whether any branch at all is useful.
let mut any_is_useful = false;
for v in vs {
let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
match res {
Useful(pats) => {
any_is_useful = true;
unreachable_pats.extend(pats);
if !any_is_useful {
any_is_useful = true;
// Initialize with the first set of unreachable subpatterns encountered.
unreachable_subpats = pats.into_iter().collect();
} else {
// Keep the patterns unreachable from both this and previous branches.
unreachable_subpats =
pats.into_iter().filter(|p| unreachable_subpats.contains(p)).collect();
}
}
NotUseful => unreachable_pats.push(v.head()),
NotUseful => unreachable_branches.push(v.head().span),
UsefulWithWitness(_) => {
bug!("Encountered or-pat in `v` during exhaustiveness checking")
}
@ -1871,7 +1891,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
matrix.push(v);
}
}
return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
if any_is_useful {
// Collect all the unreachable patterns.
unreachable_branches.extend(unreachable_subpats);
return Useful(unreachable_branches);
} else {
return NotUseful;
}
}
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
@ -2014,7 +2040,7 @@ fn is_useful_specialized<'p, 'tcx>(
witness_preference: WitnessPreference,
hir_id: HirId,
is_under_guard: bool,
) -> Usefulness<'tcx, 'p> {
) -> Usefulness<'tcx> {
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty);
// We cache the result of `Fields::wildcards` because it is used a lot.

View file

@ -12,6 +12,7 @@
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{HirId, Pat};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::nightly_options;
use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
use rustc_session::parse::feature_err;
@ -392,8 +393,8 @@ fn check_arms<'p, 'tcx>(
}
}
Useful(unreachable_subpatterns) => {
for pat in unreachable_subpatterns {
unreachable_pattern(cx.tcx, pat.span, id, None);
for span in unreachable_subpatterns {
unreachable_pattern(cx.tcx, span, id, None);
}
}
UsefulWithWitness(_) => bug!(),
@ -487,9 +488,27 @@ fn check_exhaustive<'p, 'tcx>(
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
err.help(
"ensure that all possible cases are being handled, \
possibly by adding wildcards or more match arms",
possibly by adding wildcards or more match arms",
);
err.note(&format!("the matched value is of type `{}`", scrut_ty));
if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize)
&& !is_empty_match
&& witnesses.len() == 1
&& witnesses[0].is_wildcard()
{
err.note(&format!(
"`{}` does not have a fixed maximum value, \
so a wildcard `_` is necessary to match exhaustively",
scrut_ty,
));
if nightly_options::is_nightly_build() {
err.help(&format!(
"add `#![feature(precise_pointer_size_matching)]` \
to the crate attributes to enable precise `{}` matching",
scrut_ty,
));
}
}
err.emit();
}

View file

@ -152,10 +152,14 @@
arm_target_feature,
asm,
assert,
assert_inhabited,
assert_uninit_valid,
assert_zero_valid,
associated_consts,
associated_type_bounds,
associated_type_defaults,
associated_types,
assume,
assume_init,
async_await,
async_closure,
@ -181,11 +185,14 @@
box_patterns,
box_syntax,
braced_empty_structs,
breakpoint,
bswap,
bitreverse,
C,
caller_location,
cdylib,
ceilf32,
ceilf64,
cfg,
cfg_accessible,
cfg_attr,
@ -239,8 +246,14 @@
convert,
Copy,
copy_closures,
copy,
copy_nonoverlapping,
copysignf32,
copysignf64,
core,
core_intrinsics,
cosf32,
cosf64,
count_code_region,
coverage_counter_add,
coverage_counter_subtract,
@ -299,6 +312,7 @@
dropck_eyepatch,
dropck_parametricity,
drop_types_in_const,
drop_in_place,
dylib,
dyn_trait,
eh_personality,
@ -311,11 +325,16 @@
Eq,
Equal,
enclosing_scope,
exact_div,
except,
exclusive_range_pattern,
exhaustive_integer_patterns,
exhaustive_patterns,
existential_type,
expf32,
expf64,
exp2f32,
exp2f64,
expected,
export_name,
expr,
@ -329,6 +348,10 @@
f16c_target_feature,
f32,
f64,
fadd_fast,
fabsf32,
fabsf64,
fdiv_fast,
feature,
ffi_const,
ffi_pure,
@ -336,13 +359,21 @@
field,
field_init_shorthand,
file,
float_to_int_unchecked,
floorf64,
floorf32,
fmaf32,
fmaf64,
fmt,
fmt_internals,
fmul_fast,
fn_must_use,
forbid,
forget,
format_args,
format_args_nl,
format_args_capture,
frem_fast,
from,
From,
from_desugaring,
@ -352,6 +383,7 @@
from_ok,
from_usize,
from_trait,
fsub_fast,
fundamental,
future,
Future,
@ -427,6 +459,7 @@
label_break_value,
lang,
lang_items,
lazy_normalization_consts,
lateout,
let_chains,
lhs,
@ -448,6 +481,12 @@
llvm_asm,
local_inner_macros,
log_syntax,
logf32,
logf64,
log10f32,
log10f64,
log2f32,
log2f64,
loop_break_value,
macro_at_most_once_rep,
macro_escape,
@ -475,10 +514,16 @@
message,
meta,
min_align_of,
min_align_of_val,
min_const_fn,
min_const_unsafe_fn,
min_specialization,
minnumf32,
minnumf64,
maxnumf32,
maxnumf64,
mips_target_feature,
miri_start_panic,
mmx_target_feature,
module,
module_path,
@ -491,6 +536,8 @@
naked,
naked_functions,
name,
nearbyintf32,
nearbyintf64,
needs_allocator,
needs_drop,
needs_panic_runtime,
@ -518,6 +565,7 @@
None,
non_exhaustive,
non_modrs_mods,
nontemporal_store,
nontrapping_fptoint: "nontrapping-fptoint",
noreturn,
no_niche,
@ -577,8 +625,16 @@
poll,
Poll,
powerpc_target_feature,
powf32,
powf64,
powif32,
powif64,
precise_pointer_size_matching,
pref_align_of,
prefetch_read_data,
prefetch_read_instruction,
prefetch_write_data,
prefetch_write_instruction,
prelude,
prelude_import,
preserves_flags,
@ -640,10 +696,14 @@
Result,
Return,
rhs,
rintf32,
rintf64,
riscv_target_feature,
rlib,
rotate_left,
rotate_right,
roundf32,
roundf64,
rt,
rtm_target_feature,
rust,
@ -726,14 +786,19 @@
simd_ffi,
simd_insert,
since,
sinf32,
sinf64,
size,
size_of,
size_of_val,
slice_patterns,
slicing_syntax,
soft,
Some,
specialization,
speed,
sqrtf32,
sqrtf64,
sse4a_target_feature,
stable,
staged_api,
@ -787,6 +852,8 @@
transparent_enums,
transparent_unions,
trivial_bounds,
truncf32,
truncf64,
Try,
try_blocks,
try_trait,
@ -809,6 +876,8 @@
u32,
u64,
u8,
unaligned_volatile_load,
unaligned_volatile_store,
unboxed_closures,
unchecked_add,
unchecked_div,
@ -824,6 +893,7 @@
universal_impl_trait,
unlikely,
unmarked_api,
unreachable,
unreachable_code,
unrestricted_attribute_tokens,
unsafe_block_in_unsafe_fn,
@ -843,12 +913,21 @@
val,
var,
variant_count,
va_arg,
va_copy,
va_end,
va_start,
vec,
Vec,
version,
vis,
visible_private_types,
volatile,
volatile_copy_memory,
volatile_copy_nonoverlapping_memory,
volatile_load,
volatile_set_memory,
volatile_store,
warn,
wasm_import_module,
wasm_target_feature,
@ -858,6 +937,7 @@
wrapping_add,
wrapping_sub,
wrapping_mul,
write_bytes,
Yield,
}
}

View file

@ -108,7 +108,7 @@ pub enum GenerateMemberConstraints {
pub trait InferCtxtExt<'tcx> {
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: DefId,
parent_def_id: LocalDefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value: &T,
@ -184,7 +184,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
/// - `value_span` -- the span where the value came from, used in error reporting
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: DefId,
parent_def_id: LocalDefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value: &T,
@ -986,7 +986,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
struct Instantiator<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
parent_def_id: DefId,
parent_def_id: LocalDefId,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
value_span: Span,
@ -1043,8 +1043,7 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T)
let parent_def_id = self.parent_def_id;
let def_scope_default = || {
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
parent_def_id
== tcx.hir().local_def_id(opaque_parent_hir_id).to_def_id()
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
};
let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
Some(Node::Item(item)) => match item.kind {
@ -1053,18 +1052,14 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T)
impl_trait_fn: Some(parent),
origin,
..
}) => (parent == self.parent_def_id, origin),
}) => (parent == self.parent_def_id.to_def_id(), origin),
// Named `type Foo = impl Bar;`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: None,
origin,
..
}) => (
may_define_opaque_type(
tcx,
self.parent_def_id.expect_local(),
opaque_hir_id,
),
may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
origin,
),
_ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),

View file

@ -5,10 +5,11 @@
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::spec::abi::Abi;
use std::iter;
@ -16,14 +17,13 @@
fn equate_intrinsic_type<'tcx>(
tcx: TyCtxt<'tcx>,
it: &hir::ForeignItem<'_>,
def_id: DefId,
n_tps: usize,
abi: Abi,
safety: hir::Unsafety,
inputs: Vec<Ty<'tcx>>,
output: Ty<'tcx>,
) {
let def_id = tcx.hir().local_def_id(it.hir_id);
match it.kind {
hir::ForeignItemKind::Fn(..) => {}
_ => {
@ -67,15 +67,43 @@ fn equate_intrinsic_type<'tcx>(
}
/// Returns `true` if the given intrinsic is unsafe to call or not.
pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
match intrinsic {
"abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val"
| "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow"
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
| "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
| "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32"
| "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal,
sym::abort
| sym::size_of
| sym::min_align_of
| sym::needs_drop
| sym::caller_location
| sym::size_of_val
| sym::min_align_of_val
| sym::add_with_overflow
| sym::sub_with_overflow
| sym::mul_with_overflow
| sym::wrapping_add
| sym::wrapping_sub
| sym::wrapping_mul
| sym::saturating_add
| sym::saturating_sub
| sym::rotate_left
| sym::rotate_right
| sym::ctpop
| sym::ctlz
| sym::cttz
| sym::bswap
| sym::bitreverse
| sym::discriminant_value
| sym::type_id
| sym::likely
| sym::unlikely
| sym::ptr_guaranteed_eq
| sym::ptr_guaranteed_ne
| sym::minnumf32
| sym::minnumf64
| sym::maxnumf32
| sym::rustc_peek
| sym::maxnumf64
| sym::type_name
| sym::variant_count => hir::Unsafety::Normal,
_ => hir::Unsafety::Unsafe,
}
}
@ -84,7 +112,9 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
/// and in libcore/intrinsics.rs
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
let name = it.ident.as_str();
let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
let intrinsic_name = tcx.item_name(def_id);
let name_str = intrinsic_name.as_str();
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
@ -98,8 +128,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
})
};
let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") {
let split: Vec<&str> = name.split('_').collect();
let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
let split: Vec<&str> = name_str.split('_').collect();
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
//We only care about the operation here
@ -129,32 +159,30 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
}
};
(n_tps, inputs, output, hir::Unsafety::Unsafe)
} else if &name[..] == "abort" {
(0, Vec::new(), tcx.types.never, hir::Unsafety::Normal)
} else if &name[..] == "unreachable" {
(0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
} else {
let unsafety = intrinsic_operation_unsafety(&name[..]);
let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), tcx.mk_unit()),
"size_of" | "pref_align_of" | "min_align_of" | "variant_count" => {
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
let (n_tps, inputs, output) = match intrinsic_name {
sym::abort => (0, Vec::new(), tcx.types.never),
sym::unreachable => (0, Vec::new(), tcx.types.never),
sym::breakpoint => (0, Vec::new(), tcx.mk_unit()),
sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => {
(1, Vec::new(), tcx.types.usize)
}
"size_of_val" | "min_align_of_val" => {
sym::size_of_val | sym::min_align_of_val => {
(1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
}
"rustc_peek" => (1, vec![param(0)], param(0)),
"caller_location" => (0, vec![], tcx.caller_location_ty()),
"assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
sym::rustc_peek => (1, vec![param(0)], param(0)),
sym::caller_location => (0, vec![], tcx.caller_location_ty()),
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
(1, Vec::new(), tcx.mk_unit())
}
"forget" => (1, vec![param(0)], tcx.mk_unit()),
"transmute" => (2, vec![param(0)], param(1)),
"move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
"prefetch_read_data"
| "prefetch_write_data"
| "prefetch_read_instruction"
| "prefetch_write_instruction" => (
sym::forget => (1, vec![param(0)], tcx.mk_unit()),
sym::transmute => (2, vec![param(0)], param(1)),
sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::prefetch_read_data
| sym::prefetch_write_data
| sym::prefetch_read_instruction
| sym::prefetch_write_instruction => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@ -162,12 +190,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_unit(),
),
"drop_in_place" => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
"needs_drop" => (1, Vec::new(), tcx.types.bool),
sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
"type_name" => (1, Vec::new(), tcx.mk_static_str()),
"type_id" => (1, Vec::new(), tcx.types.u64),
"offset" | "arith_offset" => (
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
sym::type_id => (1, Vec::new(), tcx.types.u64),
sym::offset | sym::arith_offset => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@ -175,7 +203,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
),
"copy" | "copy_nonoverlapping" => (
sym::copy | sym::copy_nonoverlapping => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@ -184,7 +212,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_unit(),
),
"volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => (
sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
@ -193,7 +221,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_unit(),
),
"write_bytes" | "volatile_set_memory" => (
sym::write_bytes | sym::volatile_set_memory => (
1,
vec![
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
@ -202,93 +230,98 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_unit(),
),
"sqrtf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"sqrtf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"powif32" => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
"powif64" => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
"sinf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"sinf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"cosf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"cosf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"powf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
"powf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
"expf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"expf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"exp2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
"exp2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
"logf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"logf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"log10f32" => (0, vec![tcx.types.f32], tcx.types.f32),
"log10f64" => (0, vec![tcx.types.f64], tcx.types.f64),
"log2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
"log2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
"fmaf32" => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
"fmaf64" => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
"fabsf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"fabsf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"minnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
"minnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
"maxnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
"maxnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
"copysignf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
"copysignf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
"floorf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"floorf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"ceilf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"ceilf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"truncf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"truncf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"rintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"rintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"nearbyintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"nearbyintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
"roundf32" => (0, vec![tcx.types.f32], tcx.types.f32),
"roundf64" => (0, vec![tcx.types.f64], tcx.types.f64),
sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
"volatile_load" | "unaligned_volatile_load" => {
sym::volatile_load | sym::unaligned_volatile_load => {
(1, vec![tcx.mk_imm_ptr(param(0))], param(0))
}
"volatile_store" | "unaligned_volatile_store" => {
sym::volatile_store | sym::unaligned_volatile_store => {
(1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit())
}
"ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap"
| "bitreverse" => (1, vec![param(0)], param(0)),
sym::ctpop
| sym::ctlz
| sym::ctlz_nonzero
| sym::cttz
| sym::cttz_nonzero
| sym::bswap
| sym::bitreverse => (1, vec![param(0)], param(0)),
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => {
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
(1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
}
"ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
}
"ptr_offset_from" => {
sym::ptr_offset_from => {
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
}
"unchecked_div" | "unchecked_rem" | "exact_div" => {
sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
(1, vec![param(0), param(0)], param(0))
}
"unchecked_shl" | "unchecked_shr" | "rotate_left" | "rotate_right" => {
sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => {
(1, vec![param(0), param(0)], param(0))
}
"unchecked_add" | "unchecked_sub" | "unchecked_mul" => {
sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
(1, vec![param(0), param(0)], param(0))
}
"wrapping_add" | "wrapping_sub" | "wrapping_mul" => {
sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
(1, vec![param(0), param(0)], param(0))
}
"saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)),
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)),
sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
(1, vec![param(0), param(0)], param(0))
}
"float_to_int_unchecked" => (2, vec![param(0)], param(1)),
sym::float_to_int_unchecked => (2, vec![param(0)], param(1)),
"assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
"unlikely" => (0, vec![tcx.types.bool], tcx.types.bool),
sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()),
sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
"discriminant_value" => {
sym::discriminant_value => {
let assoc_items =
tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
@ -303,7 +336,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
)
}
"try" => {
kw::Try => {
let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
iter::once(mut_u8),
@ -326,12 +359,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
)
}
"va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) {
sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()),
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
"va_copy" => match mk_va_list_ty(hir::Mutability::Not) {
sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
Some((va_list_ref_ty, va_list_ty)) => {
let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty);
(0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit())
@ -339,38 +372,38 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
"va_arg" => match mk_va_list_ty(hir::Mutability::Mut) {
sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)),
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
"nontemporal_store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
"miri_start_panic" => {
sym::miri_start_panic => {
// FIXME - the relevant types aren't lang items,
// so it's not trivial to check this
return;
}
"count_code_region" => {
sym::count_code_region => {
(0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
}
"coverage_counter_add" | "coverage_counter_subtract" => (
sym::coverage_counter_add | sym::coverage_counter_subtract => (
0,
vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
tcx.mk_unit(),
),
"coverage_unreachable" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
sym::coverage_unreachable => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
ref other => {
other => {
struct_span_err!(
tcx.sess,
it.span,
E0093,
"unrecognized intrinsic function: `{}`",
*other
other,
)
.span_label(it.span, "unrecognized intrinsic")
.emit();
@ -379,7 +412,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
};
(n_tps, inputs, output, unsafety)
};
equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
}
/// Type-check `extern "platform-intrinsic" { ... }` functions.
@ -389,6 +422,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
tcx.mk_ty_param(n, name)
};
let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
let name = it.ident.as_str();
let (n_tps, inputs, output) = match &*name {
@ -463,6 +497,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
equate_intrinsic_type(
tcx,
it,
def_id,
n_tps,
Abi::PlatformIntrinsic,
hir::Unsafety::Unsafe,

View file

@ -1321,8 +1321,8 @@ fn check_fn<'a, 'tcx>(
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
}
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id());
let outer_hir_id = hir.as_local_hir_id(outer_def_id.expect_local());
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
let outer_hir_id = hir.as_local_hir_id(outer_def_id);
GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
@ -3427,7 +3427,7 @@ fn instantiate_opaque_types_from_value<T: TypeFoldable<'tcx>>(
let (value, opaque_type_map) =
self.register_infer_ok_obligations(self.instantiate_opaque_types(
parent_def_id.to_def_id(),
parent_def_id,
self.body_id,
self.param_env,
value,

View file

@ -2063,7 +2063,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
ident: Ident,
) -> ty::PolyFnSig<'tcx> {
let unsafety = if abi == abi::Abi::RustIntrinsic {
intrinsic_operation_unsafety(&tcx.item_name(def_id).as_str())
intrinsic_operation_unsafety(tcx.item_name(def_id))
} else {
hir::Unsafety::Unsafe
};

View file

@ -6,6 +6,8 @@ LL | match 0usize {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `usize`
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
@ -15,6 +17,8 @@ LL | match 0isize {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `isize`
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
error: aborting due to 2 previous errors

View file

@ -0,0 +1,17 @@
mod private {
pub trait Trait {
fn trait_method(&self) {
}
}
pub trait TraitB {
fn trait_method_b(&self) {
}
}
}
pub struct FooStruct;
pub use crate::private::Trait;
impl crate::private::Trait for FooStruct {}
pub use crate::private::TraitB as TraitBRename;
impl crate::private::TraitB for FooStruct {}

View file

@ -0,0 +1,9 @@
// edition:2018
// aux-crate:reexported_trait=reexported-trait.rs
fn main() {
reexported_trait::FooStruct.trait_method();
//~^ ERROR
reexported_trait::FooStruct.trait_method_b();
//~^ ERROR
}

View file

@ -0,0 +1,27 @@
error[E0599]: no method named `trait_method` found for struct `reexported_trait::FooStruct` in the current scope
--> $DIR/issue-56175.rs:5:33
|
LL | reexported_trait::FooStruct.trait_method();
| ^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
LL | use reexported_trait::Trait;
|
error[E0599]: no method named `trait_method_b` found for struct `reexported_trait::FooStruct` in the current scope
--> $DIR/issue-56175.rs:7:33
|
LL | reexported_trait::FooStruct.trait_method_b();
| ^^^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
LL | use reexported_trait::TraitBRename;
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0599`.

View file

@ -0,0 +1,10 @@
pub const fn sof<T>() -> usize {
10
}
fn test<T>() {
let _: [u8; sof::<T>()];
//~^ ERROR the size for values of type `T`
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/feature-gate-lazy_normalization_consts.rs:6:23
|
LL | pub const fn sof<T>() -> usize {
| - required by this bound in `sof`
...
LL | fn test<T>() {
| - this type parameter needs to be `std::marker::Sized`
LL | let _: [u8; sof::<T>()];
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
help: consider relaxing the implicit `Sized` restriction
|
LL | pub const fn sof<T: ?Sized>() -> usize {
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,16 @@
// check-pass
#![feature(lazy_normalization_consts)]
#![allow(incomplete_features)]
pub struct ArpIPv4<'a> {
_s: &'a u8
}
impl<'a> ArpIPv4<'a> {
const LENGTH: usize = 20;
pub fn to_buffer() -> [u8; Self::LENGTH] {
unimplemented!()
}
}
fn main() {}

View file

@ -0,0 +1,17 @@
#![feature(lazy_normalization_consts)]
//~^ WARN the feature `lazy_normalization_consts` is incomplete
trait ArraySizeTrait {
const SIZE: usize = 0;
}
impl<T: ?Sized> ArraySizeTrait for T {
const SIZE: usize = 1;
}
struct SomeArray<T: ArraySizeTrait> {
array: [u8; T::SIZE],
//~^ ERROR constant expression depends on a generic parameter
phantom: std::marker::PhantomData<T>,
}
fn main() {}

View file

@ -0,0 +1,19 @@
warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-57739.rs:1:12
|
LL | #![feature(lazy_normalization_consts)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #72219 <https://github.com/rust-lang/rust/issues/72219> for more information
error: constant expression depends on a generic parameter
--> $DIR/issue-57739.rs:12:5
|
LL | array: [u8; T::SIZE],
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to previous error; 1 warning emitted

View file

@ -0,0 +1,14 @@
// check-pass
#![feature(lazy_normalization_consts)]
#![allow(incomplete_features)]
pub struct X<P, Q>(P, Q);
pub struct L<T: ?Sized>(T);
impl<T: ?Sized> L<T> {
const S: usize = 1;
}
impl<T> X<T, [u8; L::<T>::S]> {}
fn main() {}

View file

@ -11,13 +11,13 @@
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
let ret;
// `ret` starts off uninitialized
unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set
rustc_peek(&ret); //~ ERROR rustc_peek: bit not set
// All function formal parameters start off initialized.
unsafe { rustc_peek(&x) };
unsafe { rustc_peek(&y) };
unsafe { rustc_peek(&z) };
rustc_peek(&x);
rustc_peek(&y);
rustc_peek(&z);
ret = if test {
::std::mem::replace(x, y)
@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
};
// `z` may be uninitialized here.
unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set
rustc_peek(&z); //~ ERROR rustc_peek: bit not set
// `y` is definitely uninitialized here.
unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set
rustc_peek(&y); //~ ERROR rustc_peek: bit not set
// `x` is still (definitely) initialized (replace above is a reborrow).
unsafe { rustc_peek(&x); }
rustc_peek(&x);
::std::mem::drop(x);
// `x` is *definitely* uninitialized here
unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
// `ret` is now definitely initialized (via `if` above).
unsafe { rustc_peek(&ret); }
rustc_peek(&ret);
ret
}

View file

@ -1,26 +1,26 @@
error: rustc_peek: bit not set
--> $DIR/def-inits-1.rs:14:14
--> $DIR/def-inits-1.rs:14:5
|
LL | unsafe { rustc_peek(&ret); }
| ^^^^^^^^^^^^^^^^
LL | rustc_peek(&ret);
| ^^^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/def-inits-1.rs:30:14
--> $DIR/def-inits-1.rs:30:5
|
LL | unsafe { rustc_peek(&z); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&z);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/def-inits-1.rs:33:14
--> $DIR/def-inits-1.rs:33:5
|
LL | unsafe { rustc_peek(&y); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&y);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/def-inits-1.rs:41:14
--> $DIR/def-inits-1.rs:41:5
|
LL | unsafe { rustc_peek(&x); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&x);
| ^^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -38,7 +38,7 @@ struct PartialInteriorMut {
*rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
let val = *rmut_cell;
unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set
rustc_peek(x); //~ ERROR rustc_peek: bit not set
val
};

View file

@ -1,8 +1,8 @@
error: rustc_peek: bit not set
--> $DIR/indirect-mutation-offset.rs:41:14
--> $DIR/indirect-mutation-offset.rs:41:5
|
LL | unsafe { rustc_peek(x) };
| ^^^^^^^^^^^^^
LL | rustc_peek(x);
| ^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -11,13 +11,13 @@
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
let ret;
// `ret` starts off uninitialized, so we get an error report here.
unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set
rustc_peek(&ret); //~ ERROR rustc_peek: bit not set
// All function formal parameters start off initialized.
unsafe { rustc_peek(&x) };
unsafe { rustc_peek(&y) };
unsafe { rustc_peek(&z) };
rustc_peek(&x);
rustc_peek(&y);
rustc_peek(&z);
ret = if test {
::std::mem::replace(x, y)
@ -28,21 +28,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
// `z` may be initialized here.
unsafe { rustc_peek(&z); }
rustc_peek(&z);
// `y` is definitely uninitialized here.
unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set
rustc_peek(&y); //~ ERROR rustc_peek: bit not set
// `x` is still (definitely) initialized (replace above is a reborrow).
unsafe { rustc_peek(&x); }
rustc_peek(&x);
::std::mem::drop(x);
// `x` is *definitely* uninitialized here
unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
// `ret` is now definitely initialized (via `if` above).
unsafe { rustc_peek(&ret); }
rustc_peek(&ret);
ret
}

View file

@ -1,20 +1,20 @@
error: rustc_peek: bit not set
--> $DIR/inits-1.rs:14:14
--> $DIR/inits-1.rs:14:5
|
LL | unsafe { rustc_peek(&ret); }
| ^^^^^^^^^^^^^^^^
LL | rustc_peek(&ret);
| ^^^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/inits-1.rs:34:14
--> $DIR/inits-1.rs:34:5
|
LL | unsafe { rustc_peek(&y); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&y);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/inits-1.rs:42:14
--> $DIR/inits-1.rs:42:5
|
LL | unsafe { rustc_peek(&x); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&x);
| ^^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -10,17 +10,17 @@ fn foo() -> i32 {
x = 0;
// `x` is live here since it is used in the next statement...
unsafe { rustc_peek(x); }
rustc_peek(x);
p = &x;
// ... but not here, even while it can be accessed through `p`.
unsafe { rustc_peek(x); } //~ ERROR rustc_peek: bit not set
rustc_peek(x); //~ ERROR rustc_peek: bit not set
let tmp = unsafe { *p };
x = tmp + 1;
unsafe { rustc_peek(x); }
rustc_peek(x);
x
}

View file

@ -1,8 +1,8 @@
error: rustc_peek: bit not set
--> $DIR/liveness-ptr.rs:18:14
--> $DIR/liveness-ptr.rs:18:5
|
LL | unsafe { rustc_peek(x); }
| ^^^^^^^^^^^^^
LL | rustc_peek(x);
| ^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -11,13 +11,13 @@
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
let ret;
// `ret` starts off uninitialized
unsafe { rustc_peek(&ret); }
rustc_peek(&ret);
// All function formal parameters start off initialized.
unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set
unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
rustc_peek(&y); //~ ERROR rustc_peek: bit not set
rustc_peek(&z); //~ ERROR rustc_peek: bit not set
ret = if test {
::std::mem::replace(x, y)
@ -27,21 +27,21 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
};
// `z` may be uninitialized here.
unsafe { rustc_peek(&z); }
rustc_peek(&z);
// `y` is definitely uninitialized here.
unsafe { rustc_peek(&y); }
rustc_peek(&y);
// `x` is still (definitely) initialized (replace above is a reborrow).
unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
::std::mem::drop(x);
// `x` is *definitely* uninitialized here
unsafe { rustc_peek(&x); }
rustc_peek(&x);
// `ret` is now definitely initialized (via `if` above).
unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set
rustc_peek(&ret); //~ ERROR rustc_peek: bit not set
ret
}

View file

@ -1,32 +1,32 @@
error: rustc_peek: bit not set
--> $DIR/uninits-1.rs:18:14
--> $DIR/uninits-1.rs:18:5
|
LL | unsafe { rustc_peek(&x) };
| ^^^^^^^^^^^^^^
LL | rustc_peek(&x);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/uninits-1.rs:19:14
--> $DIR/uninits-1.rs:19:5
|
LL | unsafe { rustc_peek(&y) };
| ^^^^^^^^^^^^^^
LL | rustc_peek(&y);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/uninits-1.rs:20:14
--> $DIR/uninits-1.rs:20:5
|
LL | unsafe { rustc_peek(&z) };
| ^^^^^^^^^^^^^^
LL | rustc_peek(&z);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/uninits-1.rs:36:14
--> $DIR/uninits-1.rs:36:5
|
LL | unsafe { rustc_peek(&x); }
| ^^^^^^^^^^^^^^
LL | rustc_peek(&x);
| ^^^^^^^^^^^^^^
error: rustc_peek: bit not set
--> $DIR/uninits-1.rs:44:14
--> $DIR/uninits-1.rs:44:5
|
LL | unsafe { rustc_peek(&ret); }
| ^^^^^^^^^^^^^^^^
LL | rustc_peek(&ret);
| ^^^^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -11,12 +11,12 @@
fn foo(x: &mut S) {
// `x` is initialized here, so maybe-uninit bit is 0.
unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
::std::mem::drop(x);
// `x` definitely uninitialized here, so maybe-uninit bit is 1.
unsafe { rustc_peek(&x) };
rustc_peek(&x);
}
fn main() {
foo(&mut S(13));

View file

@ -1,8 +1,8 @@
error: rustc_peek: bit not set
--> $DIR/uninits-2.rs:14:14
--> $DIR/uninits-2.rs:14:5
|
LL | unsafe { rustc_peek(&x) };
| ^^^^^^^^^^^^^^
LL | rustc_peek(&x);
| ^^^^^^^^^^^^^^
error: stop_after_dataflow ended compilation

View file

@ -29,6 +29,9 @@ fn main() {
(1, 4 | 5) => {} //~ ERROR unreachable pattern
_ => {}
}
match (true, true) {
(false | true, false | true) => (),
}
match (Some(0u8),) {
(None | Some(1 | 2),) => {}
(Some(1),) => {} //~ ERROR unreachable pattern
@ -67,4 +70,29 @@ fn main() {
| 1) => {}
_ => {}
}
// A subpattern that is only unreachable in one branch is overall reachable.
match (true, true) {
(true, true) => {}
(false | true, false | true) => {}
}
match (true, true) {
(true, false) => {}
(false, true) => {}
(false | true, false | true) => {}
}
// A subpattern that is unreachable in all branches is overall unreachable.
match (true, true) {
(false, true) => {}
(true, true) => {}
(false | true, false
| true) => {} //~ ERROR unreachable
}
match (true, true) {
(true, false) => {}
(true, true) => {}
(false
| true, //~ ERROR unreachable
false | true) => {}
}
}

View file

@ -53,52 +53,64 @@ LL | (1, 4 | 5) => {}
| ^^^^^^^^^^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:34:9
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
|
LL | (Some(1),) => {}
| ^^^^^^^^^^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:35:9
--> $DIR/exhaustiveness-unreachable-pattern.rs:38:9
|
LL | (None,) => {}
| ^^^^^^^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:40:9
--> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
|
LL | ((1..=4,),) => {}
| ^^^^^^^^^^^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:45:14
--> $DIR/exhaustiveness-unreachable-pattern.rs:48:14
|
LL | (1 | 1,) => {}
| ^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:52:15
|
LL | | 0] => {}
| ^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:50:15
--> $DIR/exhaustiveness-unreachable-pattern.rs:53:15
|
LL | | 0
| ^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:60:10
--> $DIR/exhaustiveness-unreachable-pattern.rs:55:15
|
LL | | 0] => {}
| ^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:63:10
|
LL | [1
| ^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:14
--> $DIR/exhaustiveness-unreachable-pattern.rs:69:14
|
LL | Some(0
| ^
error: aborting due to 16 previous errors
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:89:15
|
LL | | true) => {}
| ^^^^
error: unreachable pattern
--> $DIR/exhaustiveness-unreachable-pattern.rs:95:15
|
LL | | true,
| ^^^^
error: aborting due to 18 previous errors

View file

@ -3,7 +3,6 @@
// run-pass
#![feature(or_patterns)]
#![allow(unreachable_patterns)] // FIXME(or-patterns) this shouldn't trigger
fn search(target: (bool, bool, bool)) -> u32 {
let x = ((false, true), (false, true), (false, true));

View file

@ -0,0 +1,23 @@
use std::{usize, isize};
fn main() {
match 0usize {
//~^ ERROR non-exhaustive patterns
//~| NOTE pattern `_` not covered
//~| NOTE the matched value is of type `usize`
//~| NOTE `usize` does not have a fixed maximum value
0 ..= usize::MAX => {}
}
match 0isize {
//~^ ERROR non-exhaustive patterns
//~| NOTE pattern `_` not covered
//~| NOTE the matched value is of type `isize`
//~| NOTE `isize` does not have a fixed maximum value
isize::MIN ..= isize::MAX => {}
}
match 7usize {}
//~^ ERROR non-exhaustive patterns
//~| NOTE the matched value is of type `usize`
}

View file

@ -0,0 +1,34 @@
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/non-exhaustive-pattern-pointer-size-int.rs:4:11
|
LL | match 0usize {
| ^^^^^^ pattern `_` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `usize`
= note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/non-exhaustive-pattern-pointer-size-int.rs:12:11
|
LL | match 0isize {
| ^^^^^^ pattern `_` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `isize`
= note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
--> $DIR/non-exhaustive-pattern-pointer-size-int.rs:20:11
|
LL | match 7usize {}
| ^^^^^^
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `usize`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0004`.