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:
commit
0c03aee8b8
|
@ -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
|
||||||
|
```
|
|
@ -1774,6 +1774,15 @@ impl FromIterator<String> for 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")]
|
#[stable(feature = "herd_cows", since = "1.19.0")]
|
||||||
impl<'a> FromIterator<Cow<'a, str>> for String {
|
impl<'a> FromIterator<Cow<'a, str>> for String {
|
||||||
fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
|
fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
|
||||||
|
@ -1842,6 +1851,13 @@ impl<'a> Extend<&'a str> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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")]
|
#[stable(feature = "extend_string", since = "1.4.0")]
|
||||||
impl Extend<String> for String {
|
impl Extend<String> for String {
|
||||||
fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
|
fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
|
||||||
|
|
|
@ -419,8 +419,7 @@ impl<T> Arc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "arc_unique", since = "1.4.0")]
|
#[stable(feature = "arc_unique", since = "1.4.0")]
|
||||||
pub fn try_unwrap(this: Self) -> Result<T, Self> {
|
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, Relaxed, Relaxed).is_err() {
|
||||||
if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() {
|
|
||||||
return Err(this);
|
return Err(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2004,12 +2004,6 @@ extern "rust-intrinsic" {
|
||||||
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
|
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
|
// 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>.
|
// 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
|
// (`transmute` also falls into this category, but it cannot be wrapped due to the
|
||||||
|
|
|
@ -1521,7 +1521,7 @@ pub trait Iterator {
|
||||||
///
|
///
|
||||||
/// let iter = a.iter();
|
/// 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);
|
/// assert_eq!(sum, 6);
|
||||||
///
|
///
|
||||||
|
@ -1535,7 +1535,7 @@ pub trait Iterator {
|
||||||
/// let mut iter = a.iter();
|
/// let mut iter = a.iter();
|
||||||
///
|
///
|
||||||
/// // instead, we add in a .by_ref()
|
/// // 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);
|
/// assert_eq!(sum, 3);
|
||||||
///
|
///
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
#![feature(unsized_locals)]
|
#![feature(unsized_locals)]
|
||||||
#![feature(untagged_unions)]
|
#![feature(untagged_unions)]
|
||||||
#![feature(unwind_attributes)]
|
#![feature(unwind_attributes)]
|
||||||
#![feature(variant_count)]
|
#![cfg_attr(not(bootstrap), feature(variant_count))]
|
||||||
#![feature(doc_alias)]
|
#![feature(doc_alias)]
|
||||||
#![feature(mmx_target_feature)]
|
#![feature(mmx_target_feature)]
|
||||||
#![feature(tbm_target_feature)]
|
#![feature(tbm_target_feature)]
|
||||||
|
|
|
@ -1037,6 +1037,7 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
|
||||||
/// assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
|
/// assert_eq!(mem::variant_count::<Result<!, !>>(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
#[unstable(feature = "variant_count", issue = "73662")]
|
#[unstable(feature = "variant_count", issue = "73662")]
|
||||||
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
|
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
|
||||||
pub const fn variant_count<T>() -> usize {
|
pub const fn variant_count<T>() -> usize {
|
||||||
|
|
|
@ -570,6 +570,9 @@ declare_features! (
|
||||||
/// Allows capturing variables in scope using format_args!
|
/// Allows capturing variables in scope using format_args!
|
||||||
(active, format_args_capture, "1.46.0", Some(67984), None),
|
(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
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
@ -586,5 +589,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
|
||||||
sym::raw_dylib,
|
sym::raw_dylib,
|
||||||
sym::const_trait_impl,
|
sym::const_trait_impl,
|
||||||
sym::const_trait_bound_opt_out,
|
sym::const_trait_bound_opt_out,
|
||||||
|
sym::lazy_normalization_consts,
|
||||||
sym::specialization,
|
sym::specialization,
|
||||||
];
|
];
|
||||||
|
|
|
@ -112,7 +112,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
||||||
|
|
||||||
// All other cases of inference are errors
|
// All other cases of inference are errors
|
||||||
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
|
(&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),
|
_ => ty::relate::super_relate_tys(relation, a, b),
|
||||||
|
@ -701,7 +701,7 @@ pub fn const_unification_error<'tcx>(
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
(a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>),
|
(a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>),
|
||||||
) -> TypeError<'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>(
|
fn int_unification_error<'tcx>(
|
||||||
|
@ -709,7 +709,7 @@ fn int_unification_error<'tcx>(
|
||||||
v: (ty::IntVarValue, ty::IntVarValue),
|
v: (ty::IntVarValue, ty::IntVarValue),
|
||||||
) -> TypeError<'tcx> {
|
) -> TypeError<'tcx> {
|
||||||
let (a, b) = v;
|
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>(
|
fn float_unification_error<'tcx>(
|
||||||
|
@ -717,5 +717,5 @@ fn float_unification_error<'tcx>(
|
||||||
v: (ty::FloatVarValue, ty::FloatVarValue),
|
v: (ty::FloatVarValue, ty::FloatVarValue),
|
||||||
) -> TypeError<'tcx> {
|
) -> TypeError<'tcx> {
|
||||||
let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
|
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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1370,7 +1370,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// we still evaluate them eagerly.
|
/// we still evaluate them eagerly.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn lazy_normalization(self) -> bool {
|
pub fn lazy_normalization(self) -> bool {
|
||||||
self.features().const_generics
|
self.features().const_generics || self.features().lazy_normalization_consts
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -282,26 +282,27 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
// where there is no explicit `extern crate`, we just prepend
|
// where there is no explicit `extern crate`, we just prepend
|
||||||
// the crate name.
|
// the crate name.
|
||||||
match self.tcx().extern_crate(def_id) {
|
match self.tcx().extern_crate(def_id) {
|
||||||
Some(&ExternCrate {
|
Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
|
||||||
src: ExternCrateSource::Extern(def_id),
|
(ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
|
||||||
dependency_of: LOCAL_CRATE,
|
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||||
span,
|
return Ok((
|
||||||
..
|
if !span.is_dummy() {
|
||||||
}) => {
|
self.print_def_path(def_id, &[])?
|
||||||
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
} else {
|
||||||
return Ok((
|
self.path_crate(cnum)?
|
||||||
if !span.is_dummy() {
|
},
|
||||||
self.print_def_path(def_id, &[])?
|
true,
|
||||||
} else {
|
));
|
||||||
self.path_crate(cnum)?
|
}
|
||||||
},
|
(ExternCrateSource::Path, LOCAL_CRATE) => {
|
||||||
true,
|
debug!("try_print_visible_def_path: def_id={:?}", def_id);
|
||||||
));
|
return Ok((self.path_crate(cnum)?, true));
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
None => {
|
None => {
|
||||||
return Ok((self.path_crate(cnum)?, true));
|
return Ok((self.path_crate(cnum)?, true));
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,8 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
|
||||||
if a.c_variadic != b.c_variadic {
|
if a.c_variadic != b.c_variadic {
|
||||||
return Err(TypeError::VariadicMismatch(expected_found(
|
return Err(TypeError::VariadicMismatch(expected_found(
|
||||||
relation,
|
relation,
|
||||||
&a.c_variadic,
|
a.c_variadic,
|
||||||
&b.c_variadic,
|
b.c_variadic,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let unsafety = relation.relate(a.unsafety, b.unsafety)?;
|
let unsafety = relation.relate(a.unsafety, b.unsafety)?;
|
||||||
|
@ -200,7 +200,7 @@ impl<'tcx> Relate<'tcx> for ast::Unsafety {
|
||||||
b: ast::Unsafety,
|
b: ast::Unsafety,
|
||||||
) -> RelateResult<'tcx, ast::Unsafety> {
|
) -> RelateResult<'tcx, ast::Unsafety> {
|
||||||
if a != b {
|
if a != b {
|
||||||
Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b)))
|
Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
|
||||||
} else {
|
} else {
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ impl<'tcx> Relate<'tcx> for abi::Abi {
|
||||||
a: abi::Abi,
|
a: abi::Abi,
|
||||||
b: abi::Abi,
|
b: abi::Abi,
|
||||||
) -> RelateResult<'tcx, 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 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
|
||||||
if a.item_def_id != b.item_def_id {
|
if a.item_def_id != b.item_def_id {
|
||||||
Err(TypeError::ProjectionMismatched(expected_found(
|
Err(TypeError::ProjectionMismatched(expected_found(
|
||||||
relation,
|
relation,
|
||||||
&a.item_def_id,
|
a.item_def_id,
|
||||||
&b.item_def_id,
|
b.item_def_id,
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
let substs = relation.relate(a.substs, b.substs)?;
|
let substs = relation.relate(a.substs, b.substs)?;
|
||||||
|
@ -245,8 +245,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||||
if a.item_def_id != b.item_def_id {
|
if a.item_def_id != b.item_def_id {
|
||||||
Err(TypeError::ProjectionMismatched(expected_found(
|
Err(TypeError::ProjectionMismatched(expected_found(
|
||||||
relation,
|
relation,
|
||||||
&a.item_def_id,
|
a.item_def_id,
|
||||||
&b.item_def_id,
|
b.item_def_id,
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
|
let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
|
||||||
|
@ -264,7 +264,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
|
||||||
) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
|
) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
|
||||||
// Different traits cannot be related.
|
// Different traits cannot be related.
|
||||||
if a.def_id != b.def_id {
|
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 {
|
} else {
|
||||||
let substs = relate_substs(relation, None, a.substs, b.substs)?;
|
let substs = relate_substs(relation, None, a.substs, b.substs)?;
|
||||||
Ok(ty::TraitRef { def_id: a.def_id, substs })
|
Ok(ty::TraitRef { def_id: a.def_id, substs })
|
||||||
|
@ -280,7 +280,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||||
) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
|
) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
|
||||||
// Different traits cannot be related.
|
// Different traits cannot be related.
|
||||||
if a.def_id != b.def_id {
|
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 {
|
} else {
|
||||||
let substs = relate_substs(relation, None, a.substs, b.substs)?;
|
let substs = relate_substs(relation, None, a.substs, b.substs)?;
|
||||||
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
|
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
|
||||||
|
@ -305,6 +305,7 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
|
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
|
||||||
|
#[inline]
|
||||||
fn relate<R: TypeRelation<'tcx>>(
|
fn relate<R: TypeRelation<'tcx>>(
|
||||||
relation: &mut R,
|
relation: &mut R,
|
||||||
a: Ty<'tcx>,
|
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());
|
let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
|
||||||
match (sz_a, sz_b) {
|
match (sz_a, sz_b) {
|
||||||
(Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize(
|
(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),
|
_ => 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())),
|
as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
|
||||||
)?)
|
)?)
|
||||||
} else if !(as_.is_empty() || bs.is_empty()) {
|
} 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 {
|
} 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))
|
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 {
|
if a_instance == b_instance {
|
||||||
Ok(ConstValue::Scalar(a_val))
|
Ok(ConstValue::Scalar(a_val))
|
||||||
} else {
|
} else {
|
||||||
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
|
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
if a_bytes == b_bytes {
|
||||||
Ok(a_val)
|
Ok(a_val)
|
||||||
} else {
|
} 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)
|
Ok(a_val)
|
||||||
} else {
|
} 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
|
// FIXME(const_generics): There are probably some `TyKind`s
|
||||||
|
@ -564,12 +565,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
&format!("unexpected consts: a: {:?}, b: {:?}", a, b),
|
&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)
|
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)?;
|
relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
|
||||||
Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
|
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 }))
|
new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
|
||||||
}
|
}
|
||||||
|
@ -607,7 +608,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||||
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
|
||||||
b_v.dedup();
|
b_v.dedup();
|
||||||
if a_v.len() != b_v.len() {
|
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)| {
|
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
|
||||||
|
@ -616,7 +617,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
|
||||||
(Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
|
(Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
|
||||||
(Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
|
(Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
|
||||||
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
|
(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)?)
|
Ok(tcx.mk_existential_predicates(v)?)
|
||||||
|
@ -740,20 +741,14 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Error handling
|
// 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
|
where
|
||||||
R: TypeRelation<'tcx>,
|
R: TypeRelation<'tcx>,
|
||||||
T: Clone,
|
|
||||||
{
|
{
|
||||||
expected_found_bool(relation.a_is_expected(), a, b)
|
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>
|
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();
|
|
||||||
if a_is_expected {
|
if a_is_expected {
|
||||||
ExpectedFound { expected: a, found: b }
|
ExpectedFound { expected: a, found: b }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -122,7 +122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
if let Err(terr) = self.eq_opaque_type_and_type(
|
if let Err(terr) = self.eq_opaque_type_and_type(
|
||||||
mir_output_ty,
|
mir_output_ty,
|
||||||
normalized_output_ty,
|
normalized_output_ty,
|
||||||
self.mir_def_id.to_def_id(),
|
self.mir_def_id,
|
||||||
Locations::All(output_span),
|
Locations::All(output_span),
|
||||||
ConstraintCategory::BoringNoLocation,
|
ConstraintCategory::BoringNoLocation,
|
||||||
) {
|
) {
|
||||||
|
@ -145,7 +145,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
if let Err(err) = self.eq_opaque_type_and_type(
|
if let Err(err) = self.eq_opaque_type_and_type(
|
||||||
mir_output_ty,
|
mir_output_ty,
|
||||||
user_provided_output_ty,
|
user_provided_output_ty,
|
||||||
self.mir_def_id.to_def_id(),
|
self.mir_def_id,
|
||||||
Locations::All(output_span),
|
Locations::All(output_span),
|
||||||
ConstraintCategory::BoringNoLocation,
|
ConstraintCategory::BoringNoLocation,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1144,7 +1144,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
// When you have `let x: impl Foo = ...` in a closure,
|
// When you have `let x: impl Foo = ...` in a closure,
|
||||||
// the resulting inferend values are stored with the
|
// the resulting inferend values are stored with the
|
||||||
// def-id of the base function.
|
// 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);
|
return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
|
||||||
} else {
|
} else {
|
||||||
return Err(terr);
|
return Err(terr);
|
||||||
|
@ -1208,7 +1209,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
revealed_ty: Ty<'tcx>,
|
revealed_ty: Ty<'tcx>,
|
||||||
anon_ty: Ty<'tcx>,
|
anon_ty: Ty<'tcx>,
|
||||||
anon_owner_def_id: DefId,
|
anon_owner_def_id: LocalDefId,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory,
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
|
@ -1238,8 +1239,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
let body = self.body;
|
let body = self.body;
|
||||||
let concrete_opaque_types =
|
let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types;
|
||||||
&tcx.typeck_tables_of(anon_owner_def_id.expect_local()).concrete_opaque_types;
|
|
||||||
let mut opaque_type_values = Vec::new();
|
let mut opaque_type_values = Vec::new();
|
||||||
|
|
||||||
debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
|
debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
|
||||||
|
|
|
@ -334,9 +334,9 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
v
|
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!
|
// 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
|
// 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
|
// a backwards compatibility hazard (and will break old versions of winapi for
|
||||||
// sure)
|
// sure)
|
||||||
|
@ -346,7 +346,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
// validation thus preventing such a hard error from being a backwards
|
// validation thus preventing such a hard error from being a backwards
|
||||||
// compatibility hazard
|
// compatibility hazard
|
||||||
DefKind::Const | DefKind::AssocConst => {
|
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(
|
err.report_as_lint(
|
||||||
tcx.at(tcx.def_span(def_id)),
|
tcx.at(tcx.def_span(def_id)),
|
||||||
"any use of this value will cause an error",
|
"any use of this value will cause an error",
|
||||||
|
@ -369,7 +369,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
||||||
err.report_as_lint(
|
err.report_as_lint(
|
||||||
tcx.at(span),
|
tcx.at(span),
|
||||||
"reaching this expression at runtime will panic or abort",
|
"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),
|
Some(err.span),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub mod validation;
|
||||||
pub struct ConstCx<'mir, 'tcx> {
|
pub struct ConstCx<'mir, 'tcx> {
|
||||||
pub body: &'mir mir::Body<'tcx>,
|
pub body: &'mir mir::Body<'tcx>,
|
||||||
pub tcx: TyCtxt<'tcx>,
|
pub tcx: TyCtxt<'tcx>,
|
||||||
pub def_id: DefId,
|
pub def_id: LocalDefId,
|
||||||
pub param_env: ty::ParamEnv<'tcx>,
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
pub const_kind: Option<hir::ConstContext>,
|
pub const_kind: Option<hir::ConstContext>,
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ impl ConstCx<'mir, 'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let const_kind = tcx.hir().body_const_context(def_id);
|
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.).
|
/// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).
|
||||||
|
|
|
@ -29,13 +29,7 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ccx = ConstCx {
|
let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
|
||||||
body,
|
|
||||||
tcx,
|
|
||||||
def_id: def_id.to_def_id(),
|
|
||||||
const_kind,
|
|
||||||
param_env: tcx.param_env(def_id),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
|
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ impl Qualif for CustomEq {
|
||||||
// because that component may be part of an enum variant (e.g.,
|
// 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
|
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
|
||||||
// structural-match (`Option::None`).
|
// 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()
|
traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
// without breaking stable code?
|
// without breaking stable code?
|
||||||
MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
|
MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
|
||||||
.unsound_ignore_borrow_on_drop()
|
.unsound_ignore_borrow_on_drop()
|
||||||
.into_engine(tcx, &body, def_id)
|
.into_engine(tcx, &body, def_id.to_def_id())
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(&body)
|
.into_results_cursor(&body)
|
||||||
});
|
});
|
||||||
|
@ -83,7 +83,7 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||||
|
|
||||||
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
|
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
|
||||||
.into_engine(tcx, &body, def_id)
|
.into_engine(tcx, &body, def_id.to_def_id())
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(&body)
|
.into_results_cursor(&body)
|
||||||
});
|
});
|
||||||
|
@ -110,7 +110,7 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
let ConstCx { tcx, body, def_id, .. } = *ccx;
|
||||||
|
|
||||||
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
|
FlowSensitiveAnalysis::new(HasMutInterior, ccx)
|
||||||
.into_engine(tcx, &body, def_id)
|
.into_engine(tcx, &body, def_id.to_def_id())
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(&body)
|
.into_results_cursor(&body)
|
||||||
});
|
});
|
||||||
|
@ -153,7 +153,7 @@ impl Qualifs<'mir, 'tcx> {
|
||||||
|
|
||||||
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
|
hir::ConstContext::Const | hir::ConstContext::Static(_) => {
|
||||||
let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
|
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()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(&ccx.body);
|
.into_results_cursor(&ccx.body);
|
||||||
|
|
||||||
|
@ -195,13 +195,13 @@ impl Validator<'mir, 'tcx> {
|
||||||
let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
|
let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
|
||||||
|
|
||||||
let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn)
|
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;
|
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
|
||||||
|
|
||||||
if use_min_const_fn_checks {
|
if use_min_const_fn_checks {
|
||||||
// Enforce `min_const_fn` for stable `const fn`s.
|
// Enforce `min_const_fn` for stable `const fn`s.
|
||||||
use crate::transform::qualify_min_const_fn::is_min_const_fn;
|
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);
|
error_min_const_fn_violation(tcx, span, err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -212,10 +212,10 @@ impl Validator<'mir, 'tcx> {
|
||||||
// Ensure that the end result is `Sync` in a non-thread local `static`.
|
// Ensure that the end result is `Sync` in a non-thread local `static`.
|
||||||
let should_check_for_sync = const_kind
|
let should_check_for_sync = const_kind
|
||||||
== Some(hir::ConstContext::Static(hir::Mutability::Not))
|
== 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 {
|
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);
|
check_return_ty_is_sync(tcx, &body, hir_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,7 +535,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||||
// `#[allow_internal_unstable]`.
|
// `#[allow_internal_unstable]`.
|
||||||
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
|
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
|
||||||
if !self.span.allows_unstable(feature)
|
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));
|
self.check_op(ops::FnCallUnstable(def_id, feature));
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,8 @@ pub fn run_passes(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
|
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`.
|
// No need to const-check a non-const `fn`.
|
||||||
if const_kind.is_none() {
|
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
|
// cannot yet be stolen), because `mir_validated()`, which steals
|
||||||
// from `mir_const(), forces this query to execute before
|
// from `mir_const(), forces this query to execute before
|
||||||
// performing the steal.
|
// 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() {
|
if body.return_ty().references_error() {
|
||||||
tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors");
|
tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors");
|
||||||
|
|
|
@ -60,15 +60,16 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_id = src.def_id();
|
let def_id = src.def_id().expect_local();
|
||||||
|
|
||||||
let mut rpo = traversal::reverse_postorder(body);
|
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 (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo);
|
||||||
|
|
||||||
let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates);
|
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);
|
self.promoted_fragments.set(promoted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -724,7 +725,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
ty::FnDef(def_id, _) => {
|
ty::FnDef(def_id, _) => {
|
||||||
is_const_fn(self.tcx, def_id)
|
is_const_fn(self.tcx, def_id)
|
||||||
|| is_unstable_const_fn(self.tcx, def_id).is_some()
|
|| 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,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -276,6 +276,7 @@ use self::Usefulness::*;
|
||||||
use self::WitnessPreference::*;
|
use self::WitnessPreference::*;
|
||||||
|
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
|
|
||||||
use super::{compare_const_vals, PatternFoldable, PatternFolder};
|
use super::{compare_const_vals, PatternFoldable, PatternFolder};
|
||||||
|
@ -1246,15 +1247,15 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[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.
|
/// 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.
|
/// Carries a list of witnesses of non-exhaustiveness.
|
||||||
UsefulWithWitness(Vec<Witness<'tcx>>),
|
UsefulWithWitness(Vec<Witness<'tcx>>),
|
||||||
NotUseful,
|
NotUseful,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, 'p> Usefulness<'tcx, 'p> {
|
impl<'tcx> Usefulness<'tcx> {
|
||||||
fn new_useful(preference: WitnessPreference) -> Self {
|
fn new_useful(preference: WitnessPreference) -> Self {
|
||||||
match preference {
|
match preference {
|
||||||
ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
|
ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
|
||||||
|
@ -1269,7 +1270,7 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_constructor(
|
fn apply_constructor<'p>(
|
||||||
self,
|
self,
|
||||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
ctor: &Constructor<'tcx>,
|
ctor: &Constructor<'tcx>,
|
||||||
|
@ -1828,7 +1829,7 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
is_under_guard: bool,
|
is_under_guard: bool,
|
||||||
is_top_level: bool,
|
is_top_level: bool,
|
||||||
) -> Usefulness<'tcx, 'p> {
|
) -> Usefulness<'tcx> {
|
||||||
let &Matrix(ref rows) = matrix;
|
let &Matrix(ref rows) = matrix;
|
||||||
debug!("is_useful({:#?}, {:#?})", matrix, v);
|
debug!("is_useful({:#?}, {:#?})", matrix, v);
|
||||||
|
|
||||||
|
@ -1852,16 +1853,35 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
// We need to push the already-seen patterns into the matrix in order to detect redundant
|
// 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.
|
// branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
|
||||||
let mut matrix = matrix.clone();
|
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;
|
let mut any_is_useful = false;
|
||||||
|
|
||||||
for v in vs {
|
for v in vs {
|
||||||
let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
|
let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
|
||||||
match res {
|
match res {
|
||||||
Useful(pats) => {
|
Useful(pats) => {
|
||||||
any_is_useful = true;
|
if !any_is_useful {
|
||||||
unreachable_pats.extend(pats);
|
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(_) => {
|
UsefulWithWitness(_) => {
|
||||||
bug!("Encountered or-pat in `v` during exhaustiveness checking")
|
bug!("Encountered or-pat in `v` during exhaustiveness checking")
|
||||||
}
|
}
|
||||||
|
@ -1871,7 +1891,13 @@ crate fn is_useful<'p, 'tcx>(
|
||||||
matrix.push(v);
|
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).
|
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
|
||||||
|
@ -2014,7 +2040,7 @@ fn is_useful_specialized<'p, 'tcx>(
|
||||||
witness_preference: WitnessPreference,
|
witness_preference: WitnessPreference,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
is_under_guard: bool,
|
is_under_guard: bool,
|
||||||
) -> Usefulness<'tcx, 'p> {
|
) -> Usefulness<'tcx> {
|
||||||
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty);
|
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty);
|
||||||
|
|
||||||
// We cache the result of `Fields::wildcards` because it is used a lot.
|
// We cache the result of `Fields::wildcards` because it is used a lot.
|
||||||
|
|
|
@ -12,6 +12,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{HirId, Pat};
|
use rustc_hir::{HirId, Pat};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
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::BINDINGS_WITH_VARIANT_NAME;
|
||||||
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
|
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
|
@ -392,8 +393,8 @@ fn check_arms<'p, 'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Useful(unreachable_subpatterns) => {
|
Useful(unreachable_subpatterns) => {
|
||||||
for pat in unreachable_subpatterns {
|
for span in unreachable_subpatterns {
|
||||||
unreachable_pattern(cx.tcx, pat.span, id, None);
|
unreachable_pattern(cx.tcx, span, id, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UsefulWithWitness(_) => bug!(),
|
UsefulWithWitness(_) => bug!(),
|
||||||
|
@ -487,9 +488,27 @@ fn check_exhaustive<'p, 'tcx>(
|
||||||
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
|
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
|
||||||
err.help(
|
err.help(
|
||||||
"ensure that all possible cases are being handled, \
|
"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));
|
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();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,10 +152,14 @@ symbols! {
|
||||||
arm_target_feature,
|
arm_target_feature,
|
||||||
asm,
|
asm,
|
||||||
assert,
|
assert,
|
||||||
|
assert_inhabited,
|
||||||
|
assert_uninit_valid,
|
||||||
|
assert_zero_valid,
|
||||||
associated_consts,
|
associated_consts,
|
||||||
associated_type_bounds,
|
associated_type_bounds,
|
||||||
associated_type_defaults,
|
associated_type_defaults,
|
||||||
associated_types,
|
associated_types,
|
||||||
|
assume,
|
||||||
assume_init,
|
assume_init,
|
||||||
async_await,
|
async_await,
|
||||||
async_closure,
|
async_closure,
|
||||||
|
@ -181,11 +185,14 @@ symbols! {
|
||||||
box_patterns,
|
box_patterns,
|
||||||
box_syntax,
|
box_syntax,
|
||||||
braced_empty_structs,
|
braced_empty_structs,
|
||||||
|
breakpoint,
|
||||||
bswap,
|
bswap,
|
||||||
bitreverse,
|
bitreverse,
|
||||||
C,
|
C,
|
||||||
caller_location,
|
caller_location,
|
||||||
cdylib,
|
cdylib,
|
||||||
|
ceilf32,
|
||||||
|
ceilf64,
|
||||||
cfg,
|
cfg,
|
||||||
cfg_accessible,
|
cfg_accessible,
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
|
@ -239,8 +246,14 @@ symbols! {
|
||||||
convert,
|
convert,
|
||||||
Copy,
|
Copy,
|
||||||
copy_closures,
|
copy_closures,
|
||||||
|
copy,
|
||||||
|
copy_nonoverlapping,
|
||||||
|
copysignf32,
|
||||||
|
copysignf64,
|
||||||
core,
|
core,
|
||||||
core_intrinsics,
|
core_intrinsics,
|
||||||
|
cosf32,
|
||||||
|
cosf64,
|
||||||
count_code_region,
|
count_code_region,
|
||||||
coverage_counter_add,
|
coverage_counter_add,
|
||||||
coverage_counter_subtract,
|
coverage_counter_subtract,
|
||||||
|
@ -299,6 +312,7 @@ symbols! {
|
||||||
dropck_eyepatch,
|
dropck_eyepatch,
|
||||||
dropck_parametricity,
|
dropck_parametricity,
|
||||||
drop_types_in_const,
|
drop_types_in_const,
|
||||||
|
drop_in_place,
|
||||||
dylib,
|
dylib,
|
||||||
dyn_trait,
|
dyn_trait,
|
||||||
eh_personality,
|
eh_personality,
|
||||||
|
@ -311,11 +325,16 @@ symbols! {
|
||||||
Eq,
|
Eq,
|
||||||
Equal,
|
Equal,
|
||||||
enclosing_scope,
|
enclosing_scope,
|
||||||
|
exact_div,
|
||||||
except,
|
except,
|
||||||
exclusive_range_pattern,
|
exclusive_range_pattern,
|
||||||
exhaustive_integer_patterns,
|
exhaustive_integer_patterns,
|
||||||
exhaustive_patterns,
|
exhaustive_patterns,
|
||||||
existential_type,
|
existential_type,
|
||||||
|
expf32,
|
||||||
|
expf64,
|
||||||
|
exp2f32,
|
||||||
|
exp2f64,
|
||||||
expected,
|
expected,
|
||||||
export_name,
|
export_name,
|
||||||
expr,
|
expr,
|
||||||
|
@ -329,6 +348,10 @@ symbols! {
|
||||||
f16c_target_feature,
|
f16c_target_feature,
|
||||||
f32,
|
f32,
|
||||||
f64,
|
f64,
|
||||||
|
fadd_fast,
|
||||||
|
fabsf32,
|
||||||
|
fabsf64,
|
||||||
|
fdiv_fast,
|
||||||
feature,
|
feature,
|
||||||
ffi_const,
|
ffi_const,
|
||||||
ffi_pure,
|
ffi_pure,
|
||||||
|
@ -336,13 +359,21 @@ symbols! {
|
||||||
field,
|
field,
|
||||||
field_init_shorthand,
|
field_init_shorthand,
|
||||||
file,
|
file,
|
||||||
|
float_to_int_unchecked,
|
||||||
|
floorf64,
|
||||||
|
floorf32,
|
||||||
|
fmaf32,
|
||||||
|
fmaf64,
|
||||||
fmt,
|
fmt,
|
||||||
fmt_internals,
|
fmt_internals,
|
||||||
|
fmul_fast,
|
||||||
fn_must_use,
|
fn_must_use,
|
||||||
forbid,
|
forbid,
|
||||||
|
forget,
|
||||||
format_args,
|
format_args,
|
||||||
format_args_nl,
|
format_args_nl,
|
||||||
format_args_capture,
|
format_args_capture,
|
||||||
|
frem_fast,
|
||||||
from,
|
from,
|
||||||
From,
|
From,
|
||||||
from_desugaring,
|
from_desugaring,
|
||||||
|
@ -352,6 +383,7 @@ symbols! {
|
||||||
from_ok,
|
from_ok,
|
||||||
from_usize,
|
from_usize,
|
||||||
from_trait,
|
from_trait,
|
||||||
|
fsub_fast,
|
||||||
fundamental,
|
fundamental,
|
||||||
future,
|
future,
|
||||||
Future,
|
Future,
|
||||||
|
@ -427,6 +459,7 @@ symbols! {
|
||||||
label_break_value,
|
label_break_value,
|
||||||
lang,
|
lang,
|
||||||
lang_items,
|
lang_items,
|
||||||
|
lazy_normalization_consts,
|
||||||
lateout,
|
lateout,
|
||||||
let_chains,
|
let_chains,
|
||||||
lhs,
|
lhs,
|
||||||
|
@ -448,6 +481,12 @@ symbols! {
|
||||||
llvm_asm,
|
llvm_asm,
|
||||||
local_inner_macros,
|
local_inner_macros,
|
||||||
log_syntax,
|
log_syntax,
|
||||||
|
logf32,
|
||||||
|
logf64,
|
||||||
|
log10f32,
|
||||||
|
log10f64,
|
||||||
|
log2f32,
|
||||||
|
log2f64,
|
||||||
loop_break_value,
|
loop_break_value,
|
||||||
macro_at_most_once_rep,
|
macro_at_most_once_rep,
|
||||||
macro_escape,
|
macro_escape,
|
||||||
|
@ -475,10 +514,16 @@ symbols! {
|
||||||
message,
|
message,
|
||||||
meta,
|
meta,
|
||||||
min_align_of,
|
min_align_of,
|
||||||
|
min_align_of_val,
|
||||||
min_const_fn,
|
min_const_fn,
|
||||||
min_const_unsafe_fn,
|
min_const_unsafe_fn,
|
||||||
min_specialization,
|
min_specialization,
|
||||||
|
minnumf32,
|
||||||
|
minnumf64,
|
||||||
|
maxnumf32,
|
||||||
|
maxnumf64,
|
||||||
mips_target_feature,
|
mips_target_feature,
|
||||||
|
miri_start_panic,
|
||||||
mmx_target_feature,
|
mmx_target_feature,
|
||||||
module,
|
module,
|
||||||
module_path,
|
module_path,
|
||||||
|
@ -491,6 +536,8 @@ symbols! {
|
||||||
naked,
|
naked,
|
||||||
naked_functions,
|
naked_functions,
|
||||||
name,
|
name,
|
||||||
|
nearbyintf32,
|
||||||
|
nearbyintf64,
|
||||||
needs_allocator,
|
needs_allocator,
|
||||||
needs_drop,
|
needs_drop,
|
||||||
needs_panic_runtime,
|
needs_panic_runtime,
|
||||||
|
@ -518,6 +565,7 @@ symbols! {
|
||||||
None,
|
None,
|
||||||
non_exhaustive,
|
non_exhaustive,
|
||||||
non_modrs_mods,
|
non_modrs_mods,
|
||||||
|
nontemporal_store,
|
||||||
nontrapping_fptoint: "nontrapping-fptoint",
|
nontrapping_fptoint: "nontrapping-fptoint",
|
||||||
noreturn,
|
noreturn,
|
||||||
no_niche,
|
no_niche,
|
||||||
|
@ -577,8 +625,16 @@ symbols! {
|
||||||
poll,
|
poll,
|
||||||
Poll,
|
Poll,
|
||||||
powerpc_target_feature,
|
powerpc_target_feature,
|
||||||
|
powf32,
|
||||||
|
powf64,
|
||||||
|
powif32,
|
||||||
|
powif64,
|
||||||
precise_pointer_size_matching,
|
precise_pointer_size_matching,
|
||||||
pref_align_of,
|
pref_align_of,
|
||||||
|
prefetch_read_data,
|
||||||
|
prefetch_read_instruction,
|
||||||
|
prefetch_write_data,
|
||||||
|
prefetch_write_instruction,
|
||||||
prelude,
|
prelude,
|
||||||
prelude_import,
|
prelude_import,
|
||||||
preserves_flags,
|
preserves_flags,
|
||||||
|
@ -640,10 +696,14 @@ symbols! {
|
||||||
Result,
|
Result,
|
||||||
Return,
|
Return,
|
||||||
rhs,
|
rhs,
|
||||||
|
rintf32,
|
||||||
|
rintf64,
|
||||||
riscv_target_feature,
|
riscv_target_feature,
|
||||||
rlib,
|
rlib,
|
||||||
rotate_left,
|
rotate_left,
|
||||||
rotate_right,
|
rotate_right,
|
||||||
|
roundf32,
|
||||||
|
roundf64,
|
||||||
rt,
|
rt,
|
||||||
rtm_target_feature,
|
rtm_target_feature,
|
||||||
rust,
|
rust,
|
||||||
|
@ -726,14 +786,19 @@ symbols! {
|
||||||
simd_ffi,
|
simd_ffi,
|
||||||
simd_insert,
|
simd_insert,
|
||||||
since,
|
since,
|
||||||
|
sinf32,
|
||||||
|
sinf64,
|
||||||
size,
|
size,
|
||||||
size_of,
|
size_of,
|
||||||
|
size_of_val,
|
||||||
slice_patterns,
|
slice_patterns,
|
||||||
slicing_syntax,
|
slicing_syntax,
|
||||||
soft,
|
soft,
|
||||||
Some,
|
Some,
|
||||||
specialization,
|
specialization,
|
||||||
speed,
|
speed,
|
||||||
|
sqrtf32,
|
||||||
|
sqrtf64,
|
||||||
sse4a_target_feature,
|
sse4a_target_feature,
|
||||||
stable,
|
stable,
|
||||||
staged_api,
|
staged_api,
|
||||||
|
@ -787,6 +852,8 @@ symbols! {
|
||||||
transparent_enums,
|
transparent_enums,
|
||||||
transparent_unions,
|
transparent_unions,
|
||||||
trivial_bounds,
|
trivial_bounds,
|
||||||
|
truncf32,
|
||||||
|
truncf64,
|
||||||
Try,
|
Try,
|
||||||
try_blocks,
|
try_blocks,
|
||||||
try_trait,
|
try_trait,
|
||||||
|
@ -809,6 +876,8 @@ symbols! {
|
||||||
u32,
|
u32,
|
||||||
u64,
|
u64,
|
||||||
u8,
|
u8,
|
||||||
|
unaligned_volatile_load,
|
||||||
|
unaligned_volatile_store,
|
||||||
unboxed_closures,
|
unboxed_closures,
|
||||||
unchecked_add,
|
unchecked_add,
|
||||||
unchecked_div,
|
unchecked_div,
|
||||||
|
@ -824,6 +893,7 @@ symbols! {
|
||||||
universal_impl_trait,
|
universal_impl_trait,
|
||||||
unlikely,
|
unlikely,
|
||||||
unmarked_api,
|
unmarked_api,
|
||||||
|
unreachable,
|
||||||
unreachable_code,
|
unreachable_code,
|
||||||
unrestricted_attribute_tokens,
|
unrestricted_attribute_tokens,
|
||||||
unsafe_block_in_unsafe_fn,
|
unsafe_block_in_unsafe_fn,
|
||||||
|
@ -843,12 +913,21 @@ symbols! {
|
||||||
val,
|
val,
|
||||||
var,
|
var,
|
||||||
variant_count,
|
variant_count,
|
||||||
|
va_arg,
|
||||||
|
va_copy,
|
||||||
|
va_end,
|
||||||
|
va_start,
|
||||||
vec,
|
vec,
|
||||||
Vec,
|
Vec,
|
||||||
version,
|
version,
|
||||||
vis,
|
vis,
|
||||||
visible_private_types,
|
visible_private_types,
|
||||||
volatile,
|
volatile,
|
||||||
|
volatile_copy_memory,
|
||||||
|
volatile_copy_nonoverlapping_memory,
|
||||||
|
volatile_load,
|
||||||
|
volatile_set_memory,
|
||||||
|
volatile_store,
|
||||||
warn,
|
warn,
|
||||||
wasm_import_module,
|
wasm_import_module,
|
||||||
wasm_target_feature,
|
wasm_target_feature,
|
||||||
|
@ -858,6 +937,7 @@ symbols! {
|
||||||
wrapping_add,
|
wrapping_add,
|
||||||
wrapping_sub,
|
wrapping_sub,
|
||||||
wrapping_mul,
|
wrapping_mul,
|
||||||
|
write_bytes,
|
||||||
Yield,
|
Yield,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ pub enum GenerateMemberConstraints {
|
||||||
pub trait InferCtxtExt<'tcx> {
|
pub trait InferCtxtExt<'tcx> {
|
||||||
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
parent_def_id: DefId,
|
parent_def_id: LocalDefId,
|
||||||
body_id: hir::HirId,
|
body_id: hir::HirId,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value: &T,
|
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
|
/// - `value_span` -- the span where the value came from, used in error reporting
|
||||||
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
parent_def_id: DefId,
|
parent_def_id: LocalDefId,
|
||||||
body_id: hir::HirId,
|
body_id: hir::HirId,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value: &T,
|
value: &T,
|
||||||
|
@ -986,7 +986,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||||
|
|
||||||
struct Instantiator<'a, 'tcx> {
|
struct Instantiator<'a, 'tcx> {
|
||||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
parent_def_id: DefId,
|
parent_def_id: LocalDefId,
|
||||||
body_id: hir::HirId,
|
body_id: hir::HirId,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value_span: Span,
|
value_span: Span,
|
||||||
|
@ -1043,8 +1043,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||||
let parent_def_id = self.parent_def_id;
|
let parent_def_id = self.parent_def_id;
|
||||||
let def_scope_default = || {
|
let def_scope_default = || {
|
||||||
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
|
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
|
||||||
parent_def_id
|
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
|
||||||
== tcx.hir().local_def_id(opaque_parent_hir_id).to_def_id()
|
|
||||||
};
|
};
|
||||||
let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
|
let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
|
||||||
Some(Node::Item(item)) => match item.kind {
|
Some(Node::Item(item)) => match item.kind {
|
||||||
|
@ -1053,18 +1052,14 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||||
impl_trait_fn: Some(parent),
|
impl_trait_fn: Some(parent),
|
||||||
origin,
|
origin,
|
||||||
..
|
..
|
||||||
}) => (parent == self.parent_def_id, origin),
|
}) => (parent == self.parent_def_id.to_def_id(), origin),
|
||||||
// Named `type Foo = impl Bar;`
|
// Named `type Foo = impl Bar;`
|
||||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||||
impl_trait_fn: None,
|
impl_trait_fn: None,
|
||||||
origin,
|
origin,
|
||||||
..
|
..
|
||||||
}) => (
|
}) => (
|
||||||
may_define_opaque_type(
|
may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
|
||||||
tcx,
|
|
||||||
self.parent_def_id.expect_local(),
|
|
||||||
opaque_hir_id,
|
|
||||||
),
|
|
||||||
origin,
|
origin,
|
||||||
),
|
),
|
||||||
_ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
|
_ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
|
||||||
|
|
|
@ -5,10 +5,11 @@ use crate::require_same_types;
|
||||||
|
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
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 rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -16,14 +17,13 @@ use std::iter;
|
||||||
fn equate_intrinsic_type<'tcx>(
|
fn equate_intrinsic_type<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
it: &hir::ForeignItem<'_>,
|
it: &hir::ForeignItem<'_>,
|
||||||
|
def_id: DefId,
|
||||||
n_tps: usize,
|
n_tps: usize,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
safety: hir::Unsafety,
|
safety: hir::Unsafety,
|
||||||
inputs: Vec<Ty<'tcx>>,
|
inputs: Vec<Ty<'tcx>>,
|
||||||
output: Ty<'tcx>,
|
output: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
let def_id = tcx.hir().local_def_id(it.hir_id);
|
|
||||||
|
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ForeignItemKind::Fn(..) => {}
|
hir::ForeignItemKind::Fn(..) => {}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -67,15 +67,43 @@ fn equate_intrinsic_type<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the given intrinsic is unsafe to call or not.
|
/// 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 {
|
match intrinsic {
|
||||||
"abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val"
|
sym::abort
|
||||||
| "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow"
|
| sym::size_of
|
||||||
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
|
| sym::min_align_of
|
||||||
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
|
| sym::needs_drop
|
||||||
| "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
|
| sym::caller_location
|
||||||
| "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32"
|
| sym::size_of_val
|
||||||
| "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal,
|
| 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,
|
_ => hir::Unsafety::Unsafe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +112,9 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
|
||||||
/// and in libcore/intrinsics.rs
|
/// and in libcore/intrinsics.rs
|
||||||
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||||
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
|
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| {
|
let mk_va_list_ty = |mutbl| {
|
||||||
tcx.lang_items().va_list().map(|did| {
|
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 (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
|
||||||
let split: Vec<&str> = name.split('_').collect();
|
let split: Vec<&str> = name_str.split('_').collect();
|
||||||
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
|
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
|
||||||
|
|
||||||
//We only care about the operation here
|
//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)
|
(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 {
|
} else {
|
||||||
let unsafety = intrinsic_operation_unsafety(&name[..]);
|
let unsafety = intrinsic_operation_unsafety(intrinsic_name);
|
||||||
let (n_tps, inputs, output) = match &name[..] {
|
let (n_tps, inputs, output) = match intrinsic_name {
|
||||||
"breakpoint" => (0, Vec::new(), tcx.mk_unit()),
|
sym::abort => (0, Vec::new(), tcx.types.never),
|
||||||
"size_of" | "pref_align_of" | "min_align_of" | "variant_count" => {
|
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)
|
(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)
|
(1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
|
||||||
}
|
}
|
||||||
"rustc_peek" => (1, vec![param(0)], param(0)),
|
sym::rustc_peek => (1, vec![param(0)], param(0)),
|
||||||
"caller_location" => (0, vec![], tcx.caller_location_ty()),
|
sym::caller_location => (0, vec![], tcx.caller_location_ty()),
|
||||||
"assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
|
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
|
||||||
(1, Vec::new(), tcx.mk_unit())
|
(1, Vec::new(), tcx.mk_unit())
|
||||||
}
|
}
|
||||||
"forget" => (1, vec![param(0)], tcx.mk_unit()),
|
sym::forget => (1, vec![param(0)], tcx.mk_unit()),
|
||||||
"transmute" => (2, vec![param(0)], param(1)),
|
sym::transmute => (2, vec![param(0)], param(1)),
|
||||||
"move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
|
sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
|
||||||
"prefetch_read_data"
|
sym::prefetch_read_data
|
||||||
| "prefetch_write_data"
|
| sym::prefetch_write_data
|
||||||
| "prefetch_read_instruction"
|
| sym::prefetch_read_instruction
|
||||||
| "prefetch_write_instruction" => (
|
| sym::prefetch_write_instruction => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
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(),
|
tcx.mk_unit(),
|
||||||
),
|
),
|
||||||
"drop_in_place" => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
|
sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
|
||||||
"needs_drop" => (1, Vec::new(), tcx.types.bool),
|
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
|
||||||
|
|
||||||
"type_name" => (1, Vec::new(), tcx.mk_static_str()),
|
sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
|
||||||
"type_id" => (1, Vec::new(), tcx.types.u64),
|
sym::type_id => (1, Vec::new(), tcx.types.u64),
|
||||||
"offset" | "arith_offset" => (
|
sym::offset | sym::arith_offset => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
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 }),
|
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
||||||
),
|
),
|
||||||
"copy" | "copy_nonoverlapping" => (
|
sym::copy | sym::copy_nonoverlapping => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
|
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(),
|
tcx.mk_unit(),
|
||||||
),
|
),
|
||||||
"volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => (
|
sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
|
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(),
|
tcx.mk_unit(),
|
||||||
),
|
),
|
||||||
"write_bytes" | "volatile_set_memory" => (
|
sym::write_bytes | sym::volatile_set_memory => (
|
||||||
1,
|
1,
|
||||||
vec![
|
vec![
|
||||||
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
|
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(),
|
tcx.mk_unit(),
|
||||||
),
|
),
|
||||||
"sqrtf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"sqrtf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"powif32" => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
|
sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
|
||||||
"powif64" => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
|
sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
|
||||||
"sinf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"sinf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"cosf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"cosf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"powf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||||
"powf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||||
"expf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"expf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"exp2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"exp2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"logf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"logf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"log10f32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"log10f64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"log2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"log2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"fmaf32" => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
sym::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),
|
sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||||
"fabsf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"fabsf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"minnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||||
"minnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||||
"maxnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||||
"maxnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||||
"copysignf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||||
"copysignf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||||
"floorf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"floorf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"ceilf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"ceilf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"truncf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"truncf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"rintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"rintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"nearbyintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"nearbyintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
|
||||||
"roundf32" => (0, vec![tcx.types.f32], tcx.types.f32),
|
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
|
||||||
"roundf64" => (0, vec![tcx.types.f64], tcx.types.f64),
|
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))
|
(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())
|
(1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit())
|
||||||
}
|
}
|
||||||
|
|
||||||
"ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap"
|
sym::ctpop
|
||||||
| "bitreverse" => (1, vec![param(0)], param(0)),
|
| 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]))
|
(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)
|
(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)
|
(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))
|
(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))
|
(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))
|
(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))
|
(1, vec![param(0), param(0)], param(0))
|
||||||
}
|
}
|
||||||
"saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)),
|
sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)),
|
||||||
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
|
||||||
(1, vec![param(0), param(0)], param(0))
|
(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()),
|
sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()),
|
||||||
"likely" => (0, vec![tcx.types.bool], tcx.types.bool),
|
sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
|
||||||
"unlikely" => (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 =
|
let assoc_items =
|
||||||
tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
|
tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
|
||||||
let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
|
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 mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
|
||||||
let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
|
let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
|
||||||
iter::once(mut_u8),
|
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()),
|
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"),
|
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)) => {
|
Some((va_list_ref_ty, va_list_ty)) => {
|
||||||
let va_list_ptr_ty = tcx.mk_mut_ptr(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())
|
(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"),
|
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)),
|
Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)),
|
||||||
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
|
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,
|
// FIXME - the relevant types aren't lang items,
|
||||||
// so it's not trivial to check this
|
// so it's not trivial to check this
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
"count_code_region" => {
|
sym::count_code_region => {
|
||||||
(0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
|
(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,
|
0,
|
||||||
vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
|
vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
|
||||||
tcx.mk_unit(),
|
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!(
|
struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
it.span,
|
it.span,
|
||||||
E0093,
|
E0093,
|
||||||
"unrecognized intrinsic function: `{}`",
|
"unrecognized intrinsic function: `{}`",
|
||||||
*other
|
other,
|
||||||
)
|
)
|
||||||
.span_label(it.span, "unrecognized intrinsic")
|
.span_label(it.span, "unrecognized intrinsic")
|
||||||
.emit();
|
.emit();
|
||||||
|
@ -379,7 +412,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||||
};
|
};
|
||||||
(n_tps, inputs, output, unsafety)
|
(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.
|
/// 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)
|
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 name = it.ident.as_str();
|
||||||
|
|
||||||
let (n_tps, inputs, output) = match &*name {
|
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(
|
equate_intrinsic_type(
|
||||||
tcx,
|
tcx,
|
||||||
it,
|
it,
|
||||||
|
def_id,
|
||||||
n_tps,
|
n_tps,
|
||||||
Abi::PlatformIntrinsic,
|
Abi::PlatformIntrinsic,
|
||||||
hir::Unsafety::Unsafe,
|
hir::Unsafety::Unsafe,
|
||||||
|
|
|
@ -1321,8 +1321,8 @@ fn check_fn<'a, 'tcx>(
|
||||||
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
|
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_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.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);
|
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`
|
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
||||||
|
@ -3427,7 +3427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
let (value, opaque_type_map) =
|
let (value, opaque_type_map) =
|
||||||
self.register_infer_ok_obligations(self.instantiate_opaque_types(
|
self.register_infer_ok_obligations(self.instantiate_opaque_types(
|
||||||
parent_def_id.to_def_id(),
|
parent_def_id,
|
||||||
self.body_id,
|
self.body_id,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
value,
|
value,
|
||||||
|
|
|
@ -2063,7 +2063,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
let unsafety = if abi == abi::Abi::RustIntrinsic {
|
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 {
|
} else {
|
||||||
hir::Unsafety::Unsafe
|
hir::Unsafety::Unsafe
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,8 @@ LL | match 0usize {
|
||||||
|
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= 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: 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
|
error[E0004]: non-exhaustive patterns: `_` not covered
|
||||||
--> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
|
--> $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
|
= 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: 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -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 {}
|
|
@ -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
|
||||||
|
}
|
|
@ -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`.
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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() {}
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
|
@ -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() {}
|
|
@ -11,13 +11,13 @@ struct S(i32);
|
||||||
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
||||||
let ret;
|
let ret;
|
||||||
// `ret` starts off uninitialized
|
// `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.
|
// All function formal parameters start off initialized.
|
||||||
|
|
||||||
unsafe { rustc_peek(&x) };
|
rustc_peek(&x);
|
||||||
unsafe { rustc_peek(&y) };
|
rustc_peek(&y);
|
||||||
unsafe { rustc_peek(&z) };
|
rustc_peek(&z);
|
||||||
|
|
||||||
ret = if test {
|
ret = if test {
|
||||||
::std::mem::replace(x, y)
|
::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.
|
// `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.
|
// `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).
|
// `x` is still (definitely) initialized (replace above is a reborrow).
|
||||||
unsafe { rustc_peek(&x); }
|
rustc_peek(&x);
|
||||||
|
|
||||||
::std::mem::drop(x);
|
::std::mem::drop(x);
|
||||||
|
|
||||||
// `x` is *definitely* uninitialized here
|
// `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).
|
// `ret` is now definitely initialized (via `if` above).
|
||||||
unsafe { rustc_peek(&ret); }
|
rustc_peek(&ret);
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
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
|
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
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ const BOO: i32 = {
|
||||||
|
|
||||||
*rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
|
*rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
|
||||||
let val = *rmut_cell;
|
let val = *rmut_cell;
|
||||||
unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set
|
rustc_peek(x); //~ ERROR rustc_peek: bit not set
|
||||||
|
|
||||||
val
|
val
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ struct S(i32);
|
||||||
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
||||||
let ret;
|
let ret;
|
||||||
// `ret` starts off uninitialized, so we get an error report here.
|
// `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.
|
// All function formal parameters start off initialized.
|
||||||
|
|
||||||
unsafe { rustc_peek(&x) };
|
rustc_peek(&x);
|
||||||
unsafe { rustc_peek(&y) };
|
rustc_peek(&y);
|
||||||
unsafe { rustc_peek(&z) };
|
rustc_peek(&z);
|
||||||
|
|
||||||
ret = if test {
|
ret = if test {
|
||||||
::std::mem::replace(x, y)
|
::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.
|
// `z` may be initialized here.
|
||||||
unsafe { rustc_peek(&z); }
|
rustc_peek(&z);
|
||||||
|
|
||||||
// `y` is definitely uninitialized here.
|
// `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).
|
// `x` is still (definitely) initialized (replace above is a reborrow).
|
||||||
unsafe { rustc_peek(&x); }
|
rustc_peek(&x);
|
||||||
|
|
||||||
::std::mem::drop(x);
|
::std::mem::drop(x);
|
||||||
|
|
||||||
// `x` is *definitely* uninitialized here
|
// `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).
|
// `ret` is now definitely initialized (via `if` above).
|
||||||
unsafe { rustc_peek(&ret); }
|
rustc_peek(&ret);
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
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
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,17 @@ fn foo() -> i32 {
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
||||||
// `x` is live here since it is used in the next statement...
|
// `x` is live here since it is used in the next statement...
|
||||||
unsafe { rustc_peek(x); }
|
rustc_peek(x);
|
||||||
|
|
||||||
p = &x;
|
p = &x;
|
||||||
|
|
||||||
// ... but not here, even while it can be accessed through `p`.
|
// ... 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 };
|
let tmp = unsafe { *p };
|
||||||
|
|
||||||
x = tmp + 1;
|
x = tmp + 1;
|
||||||
|
|
||||||
unsafe { rustc_peek(x); }
|
rustc_peek(x);
|
||||||
|
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ struct S(i32);
|
||||||
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
|
||||||
let ret;
|
let ret;
|
||||||
// `ret` starts off uninitialized
|
// `ret` starts off uninitialized
|
||||||
unsafe { rustc_peek(&ret); }
|
rustc_peek(&ret);
|
||||||
|
|
||||||
// All function formal parameters start off initialized.
|
// All function formal parameters start off initialized.
|
||||||
|
|
||||||
unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
|
rustc_peek(&x); //~ ERROR rustc_peek: bit not set
|
||||||
unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set
|
rustc_peek(&y); //~ ERROR rustc_peek: bit not set
|
||||||
unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set
|
rustc_peek(&z); //~ ERROR rustc_peek: bit not set
|
||||||
|
|
||||||
ret = if test {
|
ret = if test {
|
||||||
::std::mem::replace(x, y)
|
::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.
|
// `z` may be uninitialized here.
|
||||||
unsafe { rustc_peek(&z); }
|
rustc_peek(&z);
|
||||||
|
|
||||||
// `y` is definitely uninitialized here.
|
// `y` is definitely uninitialized here.
|
||||||
unsafe { rustc_peek(&y); }
|
rustc_peek(&y);
|
||||||
|
|
||||||
// `x` is still (definitely) initialized (replace above is a reborrow).
|
// `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);
|
::std::mem::drop(x);
|
||||||
|
|
||||||
// `x` is *definitely* uninitialized here
|
// `x` is *definitely* uninitialized here
|
||||||
unsafe { rustc_peek(&x); }
|
rustc_peek(&x);
|
||||||
|
|
||||||
// `ret` is now definitely initialized (via `if` above).
|
// `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
|
ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
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
|
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
|
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
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@ struct S(i32);
|
||||||
fn foo(x: &mut S) {
|
fn foo(x: &mut S) {
|
||||||
// `x` is initialized here, so maybe-uninit bit is 0.
|
// `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);
|
::std::mem::drop(x);
|
||||||
|
|
||||||
// `x` definitely uninitialized here, so maybe-uninit bit is 1.
|
// `x` definitely uninitialized here, so maybe-uninit bit is 1.
|
||||||
unsafe { rustc_peek(&x) };
|
rustc_peek(&x);
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
foo(&mut S(13));
|
foo(&mut S(13));
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: rustc_peek: bit not set
|
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
|
error: stop_after_dataflow ended compilation
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,9 @@ fn main() {
|
||||||
(1, 4 | 5) => {} //~ ERROR unreachable pattern
|
(1, 4 | 5) => {} //~ ERROR unreachable pattern
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
match (true, true) {
|
||||||
|
(false | true, false | true) => (),
|
||||||
|
}
|
||||||
match (Some(0u8),) {
|
match (Some(0u8),) {
|
||||||
(None | Some(1 | 2),) => {}
|
(None | Some(1 | 2),) => {}
|
||||||
(Some(1),) => {} //~ ERROR unreachable pattern
|
(Some(1),) => {} //~ ERROR unreachable pattern
|
||||||
|
@ -67,4 +70,29 @@ fn main() {
|
||||||
| 1) => {}
|
| 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) => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,52 +53,64 @@ LL | (1, 4 | 5) => {}
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:34:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
|
||||||
|
|
|
|
||||||
LL | (Some(1),) => {}
|
LL | (Some(1),) => {}
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:35:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:38:9
|
||||||
|
|
|
|
||||||
LL | (None,) => {}
|
LL | (None,) => {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:40:9
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
|
||||||
|
|
|
|
||||||
LL | ((1..=4,),) => {}
|
LL | ((1..=4,),) => {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:45:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:48:14
|
||||||
|
|
|
|
||||||
LL | (1 | 1,) => {}
|
LL | (1 | 1,) => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:52:15
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:53:15
|
||||||
|
|
|
||||||
LL | | 0] => {}
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: unreachable pattern
|
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:50:15
|
|
||||||
|
|
|
|
||||||
LL | | 0
|
LL | | 0
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
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
|
LL | [1
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:14
|
--> $DIR/exhaustiveness-unreachable-pattern.rs:69:14
|
||||||
|
|
|
|
||||||
LL | Some(0
|
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
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![allow(unreachable_patterns)] // FIXME(or-patterns) this shouldn't trigger
|
|
||||||
|
|
||||||
fn search(target: (bool, bool, bool)) -> u32 {
|
fn search(target: (bool, bool, bool)) -> u32 {
|
||||||
let x = ((false, true), (false, true), (false, true));
|
let x = ((false, true), (false, true), (false, true));
|
||||||
|
|
|
@ -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`
|
||||||
|
}
|
|
@ -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`.
|
Loading…
Reference in New Issue