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