use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
- Body, CastKind, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
- TerminatorKind, NonDivergingIntrinsic
+ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind,
+ Terminator, TerminatorKind,
};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
- ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
- ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
- ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
- ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate),
+ ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
+ ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
+ ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
+ ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
}
}
match predicates.parent {
ty::FnPtr(..) => {
return Err((span, "function pointers in const fn are unstable".into()));
},
- ty::Dynamic(preds, _) => {
+ ty::Dynamic(preds, _, _) => {
for pred in preds.iter() {
match pred.skip_binder() {
ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => {
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into()))
},
+ Rvalue::Cast(CastKind::DynStar, _, _) => {
+ // FIXME(dyn-star)
+ unimplemented!()
+ },
// binops are fine on integers
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
check_operand(tcx, lhs, span, body)?;
check_place(tcx, **place, span, body)
},
- StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
- check_operand(tcx, op, span, body)
- },
+ StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body),
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
rustc_middle::mir::CopyNonOverlapping { dst, src, count },
check_operand(tcx, src, span, body)?;
check_operand(tcx, count, span, body)
},
-
// These are all NOPs
StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
}
},
ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::Deref
span,
format!(
"can only call other `const fn` within a `const fn`, \
- but `{:?}` is not stable as `const fn`",
- func,
+ but `{func:?}` is not stable as `const fn`",
)
.into(),
));
// Checking MSRV is manually necessary because `rustc` has no such concept. This entire
// function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
// as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
+
+ // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver`
+ // doesn't accept the `-dev` version number so we have to strip it
+ // off.
+ let short_version = since
+ .as_str()
+ .split('-')
+ .next()
+ .expect("rustc_attr::StabilityLevel::Stable::since` is empty");
+
+ let since = rustc_span::Symbol::intern(short_version);
+
crate::meets_msrv(
msrv,
- RustcVersion::parse(since.as_str())
- .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"),
+ RustcVersion::parse(since.as_str()).unwrap_or_else(|err| {
+ panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")
+ }),
)
} else {
// Unstable const fn with the feature enabled.