/// [alignment]: ./fn.align_of.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn size_of<T>() -> usize {
+ intrinsics::size_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
pub const fn size_of<T>() -> usize {
unsafe { intrinsics::size_of::<T>() }
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(not(stage0))]
+pub fn min_align_of<T>() -> usize {
+ intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+pub const fn align_of<T>() -> usize {
+ intrinsics::min_align_of::<T>()
+}
+
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+/// Ceci n'est pas la documentation
pub const fn align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
match *self {
mir::UnsafetyViolationKind::General => {}
+ mir::UnsafetyViolationKind::MinConstFn => {}
mir::UnsafetyViolationKind::ExternStatic(lint_node_id) |
mir::UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
lint_node_id.hash_stable(hcx, hasher);
level,
feature,
rustc_depr,
- rustc_const_unstable
+ const_stability
});
impl<'a> HashStable<StableHashingContext<'a>>
}
impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
-impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
impl_stable_hash_for!(enum ::syntax::attr::IntType {
},
feature: Symbol::intern("rustc_private"),
rustc_depr: None,
- rustc_const_unstable: None,
+ const_stability: None,
});
annotator.parent_stab = Some(stability);
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum UnsafetyViolationKind {
General,
+ /// unsafety is not allowed at all in min const fn
+ MinConstFn,
ExternStatic(ast::NodeId),
BorrowPacked(ast::NodeId),
}
local as usize == global as usize
}
+ /// Returns true if this function must conform to `min_const_fn`
+ pub fn is_min_const_fn(self, def_id: DefId) -> bool {
+ if self.features().staged_api {
+ // some intrinsics are waved through if called inside the
+ // standard library. Users never need to call them directly
+ if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
+ assert!(!self.is_const_fn(def_id));
+ match &self.item_name(def_id).as_str()[..] {
+ | "size_of"
+ | "min_align_of"
+ => return true,
+ _ => {},
+ }
+ }
+ // in order for a libstd function to be considered min_const_fn
+ // it needs to be stable and have no `rustc_const_unstable` attribute
+ match self.lookup_stability(def_id) {
+ // stable functions with unstable const fn aren't `min_const_fn`
+ Some(&attr::Stability { const_stability: Some(_), .. }) => false,
+ // unstable functions don't need to conform
+ Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false,
+ // everything else needs to conform, because it would be callable from
+ // other `min_const_fn` functions
+ _ => true,
+ }
+ } else {
+ // users enabling the `const_fn` can do what they want
+ !self.sess.features_untracked().const_fn
+ }
+ }
+
/// Create a type context and call the closure with a `TyCtxt` reference
/// to the context. The closure enforces that the type context and any interned
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::map::blocks::FnLikeNode;
use rustc::hir::Node;
use rustc::middle::region;
use rustc::infer::InferCtxt;
let constness = match body_owner_kind {
hir::BodyOwnerKind::Const |
hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
- hir::BodyOwnerKind::Fn => {
- let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id));
- fn_like.map_or(hir::Constness::NotConst, |f| f.constness())
- }
+ hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
};
let attrs = tcx.hir.attrs(src_id);
// Respect -C overflow-checks.
check_overflow |= tcx.sess.overflow_checks();
- // Constants and const fn's always need overflow checks.
+ // Constants always need overflow checks.
check_overflow |= constness == hir::Constness::Const;
let lint_level = lint_level_for_hir_id(tcx, src_id);
pub struct UnsafetyChecker<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
+ min_const_fn: bool,
source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
violations: Vec<UnsafetyViolation>,
source_info: SourceInfo,
}
impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
- fn new(mir: &'a Mir<'tcx>,
- source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>) -> Self {
+ fn new(
+ min_const_fn: bool,
+ mir: &'a Mir<'tcx>,
+ source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Self {
Self {
mir,
+ min_const_fn,
source_scope_local_data,
violations: vec![],
source_info: SourceInfo {
fn register_violations(&mut self,
violations: &[UnsafetyViolation],
unsafe_blocks: &[(ast::NodeId, bool)]) {
+ if self.min_const_fn {
+ for violation in violations {
+ let mut violation = violation.clone();
+ violation.kind = UnsafetyViolationKind::MinConstFn;
+ if !self.violations.contains(&violation) {
+ self.violations.push(violation)
+ }
+ }
+ }
let within_unsafe = match self.source_scope_local_data[self.source_info.scope].safety {
Safety::Safe => {
for violation in violations {
self.violations.push(violation.clone())
}
}
-
false
}
Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
let param_env = tcx.param_env(def_id);
let mut checker = UnsafetyChecker::new(
+ tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id),
mir, source_scope_local_data, tcx, param_env);
checker.visit_mir(mir);
.note(&details.as_str()[..])
.emit();
}
+ UnsafetyViolationKind::MinConstFn => {
+ tcx.sess.struct_span_err(
+ source_info.span,
+ &format!("{} is unsafe and unsafe operations \
+ are not allowed in const fn", description))
+ .span_label(source_info.span, &description.as_str()[..])
+ .note(&details.as_str()[..])
+ .emit();
+ }
UnsafetyViolationKind::ExternStatic(lint_node_id) => {
tcx.lint_node_note(SAFE_EXTERN_STATICS,
lint_node_id,
pub mod add_call_guards;
pub mod promote_consts;
pub mod qualify_consts;
+mod qualify_min_const_fn;
pub mod remove_noop_landing_pads;
pub mod dump_mir;
pub mod deaggregator;
);
}
} else if let Some(&attr::Stability {
- rustc_const_unstable: Some(attr::RustcConstUnstable {
- feature: ref feature_name
- }),
+ const_stability: Some(ref feature_name),
.. }) = self.tcx.lookup_stability(def_id) {
if
// feature-gate is not enabled,
let (temps, candidates) = {
let mut qualifier = Qualifier::new(tcx, def_id, mir, mode);
if mode == Mode::ConstFn {
- // Enforce a constant-like CFG for `const fn`.
- qualifier.qualify_const();
+ if tcx.is_min_const_fn(def_id) {
+ // enforce `min_const_fn` for stable const fns
+ use super::qualify_min_const_fn::is_min_const_fn;
+ if let Err((span, err)) = is_min_const_fn(tcx, def_id, mir) {
+ tcx.sess.span_err(span, &err);
+ } else {
+ // this should not produce any errors, but better safe than sorry
+ // FIXME(#53819)
+ qualifier.qualify_const();
+ }
+ } else {
+ // Enforce a constant-like CFG for `const fn`.
+ qualifier.qualify_const();
+ }
} else {
while let Some((bb, data)) = qualifier.rpo.next() {
qualifier.visit_basic_block_data(bb, data);
--- /dev/null
+use rustc::hir::def_id::DefId;
+use rustc::hir;
+use rustc::mir::*;
+use rustc::ty::{self, Predicate, TyCtxt};
+use std::borrow::Cow;
+use syntax_pos::Span;
+
+mod helper {
+ pub struct IsMinConstFn(());
+ /// This should only ever be used *once* and then passed around as a token.
+ pub fn ensure_that_you_really_intended_to_create_an_instance_of_this() -> IsMinConstFn {
+ IsMinConstFn(())
+ }
+}
+
+use self::helper::*;
+
+type McfResult = Result<IsMinConstFn, (Span, Cow<'static, str>)>;
+
+pub fn is_min_const_fn(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId,
+ mir: &'a Mir<'tcx>,
+) -> McfResult {
+ let mut current = def_id;
+ loop {
+ let predicates = tcx.predicates_of(current);
+ for predicate in &predicates.predicates {
+ match predicate {
+ | Predicate::RegionOutlives(_)
+ | Predicate::TypeOutlives(_)
+ | Predicate::WellFormed(_)
+ | Predicate::ConstEvaluatable(..) => continue,
+ | Predicate::ObjectSafe(_) => {
+ bug!("object safe predicate on function: {:#?}", predicate)
+ }
+ Predicate::ClosureKind(..) => {
+ bug!("closure kind predicate on function: {:#?}", predicate)
+ }
+ Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
+ Predicate::Projection(_) => {
+ let span = tcx.def_span(current);
+ // we'll hit a `Predicate::Trait` later which will report an error
+ tcx.sess
+ .delay_span_bug(span, "projection without trait bound");
+ continue;
+ }
+ Predicate::Trait(pred) => {
+ if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
+ continue;
+ }
+ match pred.skip_binder().self_ty().sty {
+ ty::Param(ref p) => {
+ let generics = tcx.generics_of(current);
+ let def = generics.type_param(p, tcx);
+ let span = tcx.def_span(def.def_id);
+ return Err((
+ span,
+ "trait bounds other than `Sized` \
+ on const fn parameters are unstable"
+ .into(),
+ ));
+ }
+ // other kinds of bounds are either tautologies
+ // or cause errors in other passes
+ _ => continue,
+ }
+ }
+ }
+ }
+ match predicates.parent {
+ Some(parent) => current = parent,
+ None => break,
+ }
+ }
+
+ let mut token = ensure_that_you_really_intended_to_create_an_instance_of_this();
+
+ for local in mir.vars_iter() {
+ return Err((
+ mir.local_decls[local].source_info.span,
+ "local variables in const fn are unstable".into(),
+ ));
+ }
+ for local in &mir.local_decls {
+ token = check_ty(tcx, local.ty, local.source_info.span, token)?;
+ }
+ // impl trait is gone in MIR, so check the return type manually
+ token = check_ty(
+ tcx,
+ tcx.fn_sig(def_id).output().skip_binder(),
+ mir.local_decls.iter().next().unwrap().source_info.span,
+ token,
+ )?;
+
+ for bb in mir.basic_blocks() {
+ token = check_terminator(tcx, mir, bb.terminator(), token)?;
+ for stmt in &bb.statements {
+ token = check_statement(tcx, mir, stmt, token)?;
+ }
+ }
+ Ok(token)
+}
+
+fn check_ty(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ ty: ty::Ty<'tcx>,
+ span: Span,
+ token: IsMinConstFn,
+) -> McfResult {
+ for ty in ty.walk() {
+ match ty.sty {
+ ty::Ref(_, _, hir::Mutability::MutMutable) => return Err((
+ span,
+ "mutable references in const fn are unstable".into(),
+ )),
+ ty::Anon(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+ ty::FnPtr(..) => {
+ return Err((span, "function pointers in const fn are unstable".into()))
+ }
+ ty::Dynamic(preds, _) => {
+ for pred in preds.iter() {
+ match pred.skip_binder() {
+ | ty::ExistentialPredicate::AutoTrait(_)
+ | ty::ExistentialPredicate::Projection(_) => {
+ return Err((
+ span,
+ "trait bounds other than `Sized` \
+ on const fn parameters are unstable"
+ .into(),
+ ))
+ }
+ ty::ExistentialPredicate::Trait(trait_ref) => {
+ if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() {
+ return Err((
+ span,
+ "trait bounds other than `Sized` \
+ on const fn parameters are unstable"
+ .into(),
+ ));
+ }
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ Ok(token)
+}
+
+fn check_rvalue(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &'a Mir<'tcx>,
+ rvalue: &Rvalue<'tcx>,
+ span: Span,
+ token: IsMinConstFn,
+) -> McfResult {
+ match rvalue {
+ Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
+ check_operand(tcx, mir, operand, span, token)
+ }
+ Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
+ check_place(tcx, mir, place, span, token, PlaceMode::Read)
+ }
+ Rvalue::Cast(_, operand, cast_ty) => {
+ use rustc::ty::cast::CastTy;
+ let cast_in = CastTy::from_ty(operand.ty(mir, tcx)).expect("bad input type for cast");
+ let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+ match (cast_in, cast_out) {
+ (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => Err((
+ span,
+ "casting pointers to ints is unstable in const fn".into(),
+ )),
+ (CastTy::RPtr(_), CastTy::Float) => bug!(),
+ (CastTy::RPtr(_), CastTy::Int(_)) => bug!(),
+ (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(),
+ _ => check_operand(tcx, mir, operand, span, token),
+ }
+ }
+ // binops are fine on integers
+ Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
+ let token = check_operand(tcx, mir, lhs, span, token)?;
+ let token = check_operand(tcx, mir, rhs, span, token)?;
+ let ty = lhs.ty(mir, tcx);
+ if ty.is_integral() || ty.is_bool() || ty.is_char() {
+ Ok(token)
+ } else {
+ Err((
+ span,
+ "only int, `bool` and `char` operations are stable in const fn".into(),
+ ))
+ }
+ }
+ // checked by regular const fn checks
+ Rvalue::NullaryOp(..) => Ok(token),
+ Rvalue::UnaryOp(_, operand) => {
+ let ty = operand.ty(mir, tcx);
+ if ty.is_integral() || ty.is_bool() {
+ check_operand(tcx, mir, operand, span, token)
+ } else {
+ Err((
+ span,
+ "only int and `bool` operations are stable in const fn".into(),
+ ))
+ }
+ }
+ Rvalue::Aggregate(_, operands) => {
+ let mut token = token;
+ for operand in operands {
+ token = check_operand(tcx, mir, operand, span, token)?;
+ }
+ Ok(token)
+ }
+ }
+}
+
+enum PlaceMode {
+ Assign,
+ Read,
+}
+
+fn check_statement(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &'a Mir<'tcx>,
+ statement: &Statement<'tcx>,
+ token: IsMinConstFn,
+) -> McfResult {
+ let span = statement.source_info.span;
+ match &statement.kind {
+ StatementKind::Assign(place, rval) => {
+ let token = check_place(tcx, mir, place, span, token, PlaceMode::Assign)?;
+ check_rvalue(tcx, mir, rval, span, token)
+ }
+
+ StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())),
+
+ // just an assignment
+ StatementKind::SetDiscriminant { .. } => Ok(token),
+
+ | StatementKind::InlineAsm { .. } => {
+ Err((span, "cannot use inline assembly in const fn".into()))
+ }
+
+ // These are all NOPs
+ | StatementKind::StorageLive(_)
+ | StatementKind::StorageDead(_)
+ | StatementKind::Validate(..)
+ | StatementKind::EndRegion(_)
+ | StatementKind::UserAssertTy(..)
+ | StatementKind::Nop => Ok(token),
+ }
+}
+
+fn check_operand(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &'a Mir<'tcx>,
+ operand: &Operand<'tcx>,
+ span: Span,
+ token: IsMinConstFn,
+) -> McfResult {
+ match operand {
+ Operand::Move(place) | Operand::Copy(place) => {
+ check_place(tcx, mir, place, span, token, PlaceMode::Read)
+ }
+ Operand::Constant(_) => Ok(token),
+ }
+}
+
+fn check_place(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &'a Mir<'tcx>,
+ place: &Place<'tcx>,
+ span: Span,
+ token: IsMinConstFn,
+ mode: PlaceMode,
+) -> McfResult {
+ match place {
+ Place::Local(l) => match mode {
+ PlaceMode::Assign => match mir.local_kind(*l) {
+ LocalKind::Temp | LocalKind::ReturnPointer => Ok(token),
+ LocalKind::Arg | LocalKind::Var => {
+ Err((span, "assignments in const fn are unstable".into()))
+ }
+ },
+ PlaceMode::Read => Ok(token),
+ },
+ // promoteds are always fine, they are essentially constants
+ Place::Promoted(_) => Ok(token),
+ Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+ Place::Projection(proj) => {
+ match proj.elem {
+ | ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {
+ check_place(tcx, mir, &proj.base, span, token, mode)
+ }
+ // slice patterns are unstable
+ | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
+ return Err((span, "slice patterns in const fn are unstable".into()))
+ }
+ | ProjectionElem::Downcast(..) => {
+ Err((span, "`match` or `if let` in `const fn` is unstable".into()))
+ }
+ }
+ }
+ }
+}
+
+fn check_terminator(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ mir: &'a Mir<'tcx>,
+ terminator: &Terminator<'tcx>,
+ token: IsMinConstFn,
+) -> McfResult {
+ let span = terminator.source_info.span;
+ match &terminator.kind {
+ | TerminatorKind::Goto { .. }
+ | TerminatorKind::Return
+ | TerminatorKind::Resume => Ok(token),
+
+ TerminatorKind::Drop { location, .. } => {
+ check_place(tcx, mir, location, span, token, PlaceMode::Read)
+ }
+ TerminatorKind::DropAndReplace { location, value, .. } => {
+ let token = check_place(tcx, mir, location, span, token, PlaceMode::Read)?;
+ check_operand(tcx, mir, value, span, token)
+ },
+ TerminatorKind::SwitchInt { .. } => Err((
+ span,
+ "`if`, `match`, `&&` and `||` are not stable in const fn".into(),
+ )),
+ | TerminatorKind::Abort | TerminatorKind::Unreachable => {
+ Err((span, "const fn with unreachable code is not stable".into()))
+ }
+ | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
+ Err((span, "const fn generators are unstable".into()))
+ }
+
+ TerminatorKind::Call {
+ func,
+ args,
+ destination: _,
+ cleanup: _,
+ } => {
+ let fn_ty = func.ty(mir, tcx);
+ if let ty::FnDef(def_id, _) = fn_ty.sty {
+ if tcx.is_min_const_fn(def_id) {
+ let mut token = check_operand(tcx, mir, func, span, token)?;
+
+ for arg in args {
+ token = check_operand(tcx, mir, arg, span, token)?;
+ }
+ Ok(token)
+ } else {
+ Err((
+ span,
+ "can only call other `min_const_fn` within a `min_const_fn`".into(),
+ ))
+ }
+ } else {
+ Err((span, "can only call other const fns within const fn".into()))
+ }
+ }
+
+ TerminatorKind::Assert {
+ cond,
+ expected: _,
+ msg: _,
+ target: _,
+ cleanup: _,
+ } => check_operand(tcx, mir, cond, span, token),
+
+ | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!(
+ terminator.source_info.span,
+ "min_const_fn encountered `{:#?}`",
+ terminator
+ ),
+ }
+}
}
if let Some(&attr::Stability {
- rustc_const_unstable: Some(attr::RustcConstUnstable {
- feature: ref feature_name
- }),
+ const_stability: Some(ref feature_name),
.. }) = self.tcx.lookup_stability(def_id) {
let stable_check =
// feature-gate is enabled,
use std::iter;
-fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- it: &hir::ForeignItem,
- n_tps: usize,
- abi: Abi,
- inputs: Vec<Ty<'tcx>>,
- output: Ty<'tcx>) {
+fn equate_intrinsic_type<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ it: &hir::ForeignItem,
+ n_tps: usize,
+ abi: Abi,
+ safety: hir::Unsafety,
+ inputs: Vec<Ty<'tcx>>,
+ output: Ty<'tcx>,
+) {
let def_id = tcx.hir.local_def_id(it.id);
match it.node {
inputs.into_iter(),
output,
false,
- hir::Unsafety::Unsafe,
+ safety,
abi
)));
let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
it: &hir::ForeignItem) {
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
let name = it.name.as_str();
- let (n_tps, inputs, output) = if name.starts_with("atomic_") {
+ let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") {
let split : Vec<&str> = name.split('_').collect();
assert!(split.len() >= 2, "Atomic intrinsic not correct format");
return;
}
};
- (n_tps, inputs, output)
+ (n_tps, inputs, output, hir::Unsafety::Unsafe)
} else if &name[..] == "abort" || &name[..] == "unreachable" {
- (0, Vec::new(), tcx.types.never)
+ (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
} else {
+ let unsafety = match &name[..] {
+ "size_of" | "min_align_of" => hir::Unsafety::Normal,
+ _ => hir::Unsafety::Unsafe,
+ };
let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), tcx.mk_nil()),
"size_of" |
return;
}
};
- (n_tps, inputs, output)
+ (n_tps, inputs, output, unsafety)
};
- equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, inputs, output)
+ equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
}
/// Type-check `extern "platform-intrinsic" { ... }` functions.
}
};
- equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic,
+ equate_intrinsic_type(tcx, it, n_tps, Abi::PlatformIntrinsic, hir::Unsafety::Unsafe,
inputs, output)
}
decl: &hir::FnDecl,
abi: abi::Abi,
) -> ty::PolyFnSig<'tcx> {
- let fty = AstConv::ty_of_fn(
- &ItemCtxt::new(tcx, def_id),
- hir::Unsafety::Unsafe,
- abi,
- decl,
- );
+ let unsafety = if abi == abi::Abi::RustIntrinsic {
+ match &*tcx.item_name(def_id).as_str() {
+ "size_of" | "min_align_of" => hir::Unsafety::Normal,
+ _ => hir::Unsafety::Unsafe,
+ }
+ } else {
+ hir::Unsafety::Unsafe
+ };
+ let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl);
// feature gate SIMD types in FFI, since I (huonw) am not sure the
// ABIs are handled at all correctly.
// We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
lock: Mutex,
ptr: Cell<*mut Arc<T>>,
- init: fn() -> Arc<T>,
}
#[inline]
unsafe impl<T> Sync for Lazy<T> {}
-impl<T: Send + Sync + 'static> Lazy<T> {
- /// Safety: `init` must not call `get` on the variable that is being
- /// initialized.
- pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+impl<T> Lazy<T> {
+ pub const fn new() -> Lazy<T> {
Lazy {
lock: Mutex::new(),
ptr: Cell::new(ptr::null_mut()),
- init,
}
}
+}
- pub fn get(&'static self) -> Option<Arc<T>> {
- unsafe {
- let _guard = self.lock.lock();
- let ptr = self.ptr.get();
- if ptr.is_null() {
- Some(self.init())
- } else if ptr == done() {
- None
- } else {
- Some((*ptr).clone())
- }
+impl<T: Send + Sync + 'static> Lazy<T> {
+ /// Safety: `init` must not call `get` on the variable that is being
+ /// initialized.
+ pub unsafe fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> {
+ let _guard = self.lock.lock();
+ let ptr = self.ptr.get();
+ if ptr.is_null() {
+ Some(self.init(init))
+ } else if ptr == done() {
+ None
+ } else {
+ Some((*ptr).clone())
}
}
// Must only be called with `lock` held
- unsafe fn init(&'static self) -> Arc<T> {
+ unsafe fn init(&'static self, init: fn() -> Arc<T>) -> Arc<T> {
// If we successfully register an at exit handler, then we cache the
// `Arc` allocation in our own internal box (it will get deallocated by
// the at exit handler). Otherwise we just return the freshly allocated
});
// This could reentrantly call `init` again, which is a problem
// because our `lock` allows reentrancy!
- // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens.
- let ret = (self.init)();
+ // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens.
+ let ret = init();
if registered.is_ok() {
self.ptr.set(Box::into_raw(Box::new(ret.clone())));
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
- static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) };
+ static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
return Stdin {
- inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
+ inner: unsafe {
+ INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown")
+ },
};
fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
- static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
- = unsafe { Lazy::new(stdout_init) };
+ static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
return Stdout {
- inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
+ inner: unsafe {
+ INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown")
+ },
};
fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
- static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> =
- unsafe { Lazy::new(stderr_init) };
+ static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new();
return Stderr {
- inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
+ inner: unsafe {
+ INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown")
+ },
};
fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
pub level: StabilityLevel,
pub feature: Symbol,
pub rustc_depr: Option<RustcDeprecation>,
- pub rustc_const_unstable: Option<RustcConstUnstable>,
+ /// `None` means the function is stable but needs to be allowed by the
+ /// `min_const_fn` feature
+ /// `Some` contains the feature gate required to be able to use the function
+ /// as const fn
+ pub const_stability: Option<Symbol>,
}
/// The available stability levels.
pub reason: Symbol,
}
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
-pub struct RustcConstUnstable {
- pub feature: Symbol,
-}
-
/// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
/// This will not perform any "sanity checks" on the form of the attributes.
pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
let mut stab: Option<Stability> = None;
let mut rustc_depr: Option<RustcDeprecation> = None;
- let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
+ let mut rustc_const_unstable: Option<Symbol> = None;
'outer: for attr in attrs_iter {
if ![
mark_used(attr);
let meta = attr.meta();
+ // attributes with data
if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
let meta = meta.as_ref().unwrap();
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
get_meta!(feature);
if let Some(feature) = feature {
- rustc_const_unstable = Some(RustcConstUnstable {
- feature
- });
+ rustc_const_unstable = Some(feature);
} else {
span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
continue
},
feature,
rustc_depr: None,
- rustc_const_unstable: None,
+ const_stability: None,
})
}
(None, _, _) => {
},
feature,
rustc_depr: None,
- rustc_const_unstable: None,
+ const_stability: None,
})
}
(None, _) => {
}
// Merge the const-unstable info into the stability info
- if let Some(rustc_const_unstable) = rustc_const_unstable {
+ if let Some(feature) = rustc_const_unstable {
if let Some(ref mut stab) = stab {
- stab.rustc_const_unstable = Some(rustc_const_unstable);
+ stab.const_stability = Some(feature);
} else {
span_err!(diagnostic, item_sp, E0630,
"rustc_const_unstable attribute must be paired with \
pub use self::builtin::{
cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, IntType, ReprAttr,
- RustcConstUnstable, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
+ RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
};
pub use self::IntType::*;
pub use self::ReprAttr::*;
use std::{env, path};
macro_rules! set {
+ // The const_fn feature also enables the min_const_fn feature, because `min_const_fn` allows
+ // the declaration `const fn`, but the `const_fn` feature gate enables things inside those
+ // functions that we do not want to expose to the user for now.
+ (const_fn) => {{
+ fn f(features: &mut Features, _: Span) {
+ features.const_fn = true;
+ features.min_const_fn = true;
+ }
+ f as fn(&mut Features, Span)
+ }};
($field: ident) => {{
fn f(features: &mut Features, _: Span) {
features.$field = true;
// #23121. Array patterns have some hazards yet.
(active, slice_patterns, "1.0.0", Some(23121), None),
- // Allows the definition of `const fn` functions.
+ // Allows the definition of `const fn` functions with some advanced features.
(active, const_fn, "1.2.0", Some(24111), None),
+ // Allows the definition of `const fn` functions.
+ (active, min_const_fn, "1.30.0", Some(53555), None),
+
// Allows let bindings and destructuring in `const fn` functions and constants.
(active, const_let, "1.22.1", Some(48821), None),
- // Allows accessing fields of unions inside const fn
+ // Allows accessing fields of unions inside const fn.
(active, const_fn_union, "1.27.0", Some(51909), None),
- // Allows casting raw pointers to `usize` during const eval
+ // Allows casting raw pointers to `usize` during const eval.
(active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
- // Allows dereferencing raw pointers during const eval
+ // Allows dereferencing raw pointers during const eval.
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
- // Allows reinterpretation of the bits of a value of one type as another type during const eval
+ // Allows reinterpretation of the bits of a value of one type as another type during const eval.
(active, const_transmute, "1.29.0", Some(53605), None),
- // Allows comparing raw pointers during const eval
+ // Allows comparing raw pointers during const eval.
(active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
// Allows panicking during const eval (produces compile-time errors)
gate_feature_post!(&self, async_await, span, "async fn is unstable");
}
if header.constness.node == ast::Constness::Const {
- gate_feature_post!(&self, const_fn, span, "const fn is unstable");
+ gate_feature_post!(&self, min_const_fn, span, "const fn is unstable");
}
// stability of const fn methods are covered in
// visit_trait_item and visit_impl_item below; this is
match ii.node {
ast::ImplItemKind::Method(ref sig, _) => {
if sig.header.constness.node == ast::Constness::Const {
- gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
+ gate_feature_post!(&self, min_const_fn, ii.span, "const fn is unstable");
}
}
ast::ImplItemKind::Existential(..) => {
// ignore-emscripten
-// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no
+// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O
#![feature(const_fn)]
// END RUST SOURCE
// START rustc.const_signed.Lower128Bit.after.mir
-// _8 = _1;
-// _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10;
-// ...
-// _7 = move (_9.0: i128);
-// ...
-// _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11;
-// ...
-// _6 = move (_10.0: i128);
-// ...
-// _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12;
-// ...
-// _5 = move (_11.0: i128);
-// ...
-// _12 = Eq(const 4i128, const 0i128);
-// assert(!move _12, "attempt to divide by zero") -> bb4;
-// ...
-// _13 = Eq(const 4i128, const -1i128);
-// _14 = Eq(_5, const -170141183460469231731687303715884105728i128);
-// _15 = BitAnd(move _13, move _14);
-// assert(!move _15, "attempt to divide with overflow") -> bb5;
-// ...
-// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13;
-// ...
-// _17 = Eq(const 5i128, const -1i128);
-// _18 = Eq(_4, const -170141183460469231731687303715884105728i128);
-// _19 = BitAnd(move _17, move _18);
-// assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7;
-// ...
-// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15;
-// ...
-// _2 = move (_20.0: i128);
-// ...
-// _23 = const 7i32 as u128 (Misc);
-// _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16;
-// ...
-// _0 = move (_21.0: i128);
-// ...
-// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-// ...
-// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-// ...
-// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-// ...
-// _16 = Eq(const 5i128, const 0i128);
-// assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6;
-// ...
-// assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8;
-// ...
-// _22 = const 6i32 as u128 (Misc);
-// _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14;
-// ...
-// assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9;
+// _7 = const compiler_builtins::int::addsub::rust_i128_add(move _8, const 1i128) -> bb7;
+// ...
+// _10 = Eq(const 4i128, const -1i128);
+// _11 = Eq(_5, const -170141183460469231731687303715884105728i128);
+// _12 = BitAnd(move _10, move _11);
+// assert(!move _12, "attempt to divide with overflow") -> bb2;
+// ...
+// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb8;
+// ...
+// _14 = Eq(const 5i128, const -1i128);
+// _15 = Eq(_4, const -170141183460469231731687303715884105728i128);
+// _16 = BitAnd(move _14, move _15);
+// assert(!move _16, "attempt to calculate the remainder with overflow") -> bb4;
+// ...
+// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb11;
+// ...
+// _9 = Eq(const 4i128, const 0i128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_i128_mul(move _6, const 3i128) -> bb5;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_i128_sub(move _7, const 2i128) -> bb6;
+// ...
+// _13 = Eq(const 5i128, const 0i128);
+// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb3;
+// ...
+// _17 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_i128_shr(move _2, move _17) -> bb9;
+// ...
+// _18 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_i128_shl(move _3, move _18) -> bb10;
// END rustc.const_signed.Lower128Bit.after.mir
// START rustc.const_unsigned.Lower128Bit.after.mir
-// _8 = _1;
-// _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8;
-// ...
-// _7 = move (_9.0: u128);
-// ...
-// _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9;
-// ...
-// _6 = move (_10.0: u128);
-// ...
-// _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10;
-// ...
-// _5 = move (_11.0: u128);
-// ...
-// _12 = Eq(const 4u128, const 0u128);
-// assert(!move _12, "attempt to divide by zero") -> bb4;
-// ...
-// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11;
-// ...
-// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13;
-// ...
-// _2 = move (_14.0: u128);
-// ...
-// _17 = const 7i32 as u128 (Misc);
-// _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14;
-// ...
-// _0 = move (_15.0: u128);
-// ...
-// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1;
-// ...
-// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2;
-// ...
-// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3;
-// ...
-// _13 = Eq(const 5u128, const 0u128);
-// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5;
-// ...
-// assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6;
-// ...
-// _16 = const 6i32 as u128 (Misc);
-// _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12;
-// ...
-// assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7;
+// _8 = _1;
+// _7 = const compiler_builtins::int::addsub::rust_u128_add(move _8, const 1u128) -> bb5;
+// ...
+// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb6;
+// ...
+// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb9;
+// ...
+// _9 = Eq(const 4u128, const 0u128);
+// assert(!move _9, "attempt to divide by zero") -> bb1;
+// ...
+// _5 = const compiler_builtins::int::mul::rust_u128_mul(move _6, const 3u128) -> bb3;
+// ...
+// _6 = const compiler_builtins::int::addsub::rust_u128_sub(move _7, const 2u128) -> bb4;
+// ...
+// _10 = Eq(const 5u128, const 0u128);
+// assert(!move _10, "attempt to calculate the remainder with a divisor of zero") -> bb2;
+// ...
+// return;
+// ...
+// _11 = const 7i32 as u32 (Misc);
+// _0 = const compiler_builtins::int::shift::rust_u128_shr(move _2, move _11) -> bb7;
+// ...
+// _12 = const 6i32 as u32 (Misc);
+// _2 = const compiler_builtins::int::shift::rust_u128_shl(move _3, move _12) -> bb8;
+
// END rustc.const_unsigned.Lower128Bit.after.mir
// START rustc.test_signed.Lower128Bit.after.mir
// ignore-wasm32
// ignore-emscripten
+// compile-flags: -C debug_assertions=yes
+
#![feature(const_fn, libc)]
#![allow(const_err)]
use std::env;
use std::process::{Command, Stdio};
-// this will panic in debug mode
+// this will panic in debug mode and overflow in release mode
const fn bar() -> usize { 0 - 1 }
fn foo() {
note: ...which requires const-evaluating `Foo::bytes::{{constant}}`...
--> $SRC_DIR/libcore/mem.rs:LL:COL
|
-LL | unsafe { intrinsics::size_of::<T>() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::size_of::<T>()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires computing layout of `Foo`, completing the cycle
note: cycle used when const-evaluating `Foo::bytes::{{constant}}`
--> $SRC_DIR/libcore/mem.rs:LL:COL
|
-LL | unsafe { intrinsics::size_of::<T>() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | intrinsics::size_of::<T>()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
--- /dev/null
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:49:25
+ |
+LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:51:5
+ |
+LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:56:28
+ |
+LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:58:5
+ |
+LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:63:27
+ |
+LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:65:5
+ |
+LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:70:5
+ |
+LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:88:16
+ |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:90:18
+ |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+ | ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:92:33
+ |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+ | ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:94:35
+ |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+ | ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:96:35
+ |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+ | ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:98:43
+ |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+ | ^^^^^
+
+error: cannot access `static` items in const fn
+ --> $DIR/min_const_fn.rs:102:27
+ |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+ | ^^^
+
+error: cannot access `static` items in const fn
+ --> $DIR/min_const_fn.rs:103:36
+ |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+ | ^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:104:42
+ |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+ | ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:106:42
+ |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+ | ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:108:38
+ |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:110:29
+ |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+ | ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+ --> $DIR/min_const_fn.rs:111:34
+ |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+ | ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:112:44
+ |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+ | ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:114:44
+ |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+ | ^^^^^^
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:116:14
+ |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:121:6
+ |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:126:6
+ |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:131:6
+ |
+LL | impl<T: Sync + Sized> Foo<T> {
+ | ^
+
+error: `impl Trait` in const fn is unstable
+ --> $DIR/min_const_fn.rs:137:1
+ |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:139:34
+ |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:141:22
+ |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+ --> $DIR/min_const_fn.rs:142:1
+ |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:143:23
+ |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+ | ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:144:1
+ |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: borrowed value does not live long enough
+ --> $DIR/min_const_fn.rs:144:64
+ |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+ | ^^ - temporary value only lives until here
+ | |
+ | temporary value does not live long enough
+ |
+ = note: borrowed value must be valid for the static lifetime...
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:149:41
+ |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn.rs:152:21
+ |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+ | ^^
+
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn.rs:154:1
+ |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 36 previous errors
+
+Some errors occurred: E0493, E0597.
+For more information about an error, try `rustc --explain E0493`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const fn foo1() {}
+const fn foo2(x: i32) -> i32 { x }
+const fn foo3<T>(x: T) -> T { x }
+const fn foo7() {
+ (
+ foo1(),
+ foo2(420),
+ foo3(69),
+ ).0
+}
+const fn foo12<T: Sized>(t: T) -> T { t }
+const fn foo13<T: ?Sized>(t: &T) -> &T { t }
+const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t }
+const fn foo15<T>(t: T) -> T where T: Sized { t }
+const fn foo15_2<T>(t: &T) -> &T where T: ?Sized { t }
+const fn foo16(f: f32) -> f32 { f }
+const fn foo17(f: f32) -> u32 { f as u32 }
+const fn foo18(i: i32) -> i32 { i * 3 }
+const fn foo20(b: bool) -> bool { !b }
+const fn foo21<T, U>(t: T, u: U) -> (T, U) { (t, u) }
+const fn foo22(s: &[u8], i: usize) -> u8 { s[i] }
+const FOO: u32 = 42;
+const fn foo23() -> u32 { FOO }
+const fn foo24() -> &'static u32 { &FOO }
+const fn foo27(x: &u32) -> u32 { *x }
+const fn foo28(x: u32) -> u32 { *&x }
+const fn foo29(x: u32) -> i32 { x as i32 }
+const fn foo31(a: bool, b: bool) -> bool { a & b }
+const fn foo32(a: bool, b: bool) -> bool { a | b }
+const fn foo33(a: bool, b: bool) -> bool { a & b }
+const fn foo34(a: bool, b: bool) -> bool { a | b }
+const fn foo35(a: bool, b: bool) -> bool { a ^ b }
+struct Foo<T: ?Sized>(T);
+impl<T> Foo<T> {
+ const fn new(t: T) -> Self { Foo(t) }
+ const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+ const fn get(&self) -> &T { &self.0 }
+ const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+ //~^ mutable references in const fn are unstable
+}
+impl<'a, T> Foo<T> {
+ const fn new_lt(t: T) -> Self { Foo(t) }
+ const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+ const fn get_lt(&'a self) -> &T { &self.0 }
+ const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+ //~^ mutable references in const fn are unstable
+}
+impl<T: Sized> Foo<T> {
+ const fn new_s(t: T) -> Self { Foo(t) }
+ const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+ const fn get_s(&self) -> &T { &self.0 }
+ const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+ //~^ mutable references in const fn are unstable
+}
+impl<T: ?Sized> Foo<T> {
+ const fn get_sq(&self) -> &T { &self.0 }
+ const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+ //~^ mutable references in const fn are unstable
+}
+
+
+const fn char_ops(c: char, d: char) -> bool { c == d }
+const fn char_ops2(c: char, d: char) -> bool { c < d }
+const fn char_ops3(c: char, d: char) -> bool { c != d }
+const fn i32_ops(c: i32, d: i32) -> bool { c == d }
+const fn i32_ops2(c: i32, d: i32) -> bool { c < d }
+const fn i32_ops3(c: i32, d: i32) -> bool { c != d }
+const fn i32_ops4(c: i32, d: i32) -> i32 { c + d }
+const fn char_cast(u: u8) -> char { u as char }
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+
+// not ok
+const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo11_2<T: Send>(t: T) -> T { t }
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+const fn foo19(f: f32) -> f32 { f * 2.0 }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+const fn foo19_3(f: f32) -> f32 { -f }
+//~^ ERROR only int and `bool` operations are stable in const fn
+const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+//~^ ERROR only int, `bool` and `char` operations are stable in const fn
+
+static BAR: u32 = 42;
+const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+const fn foo30(x: *const u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_2(x: *mut u32) -> usize { x as usize }
+//~^ ERROR casting pointers to int
+const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+const fn foo36(a: bool, b: bool) -> bool { a && b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn foo37(a: bool, b: bool) -> bool { a || b }
+//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
+const fn inc(x: &mut i32) { *x += 1 }
+//~^ ERROR mutable references in const fn are unstable
+
+fn main() {}
+
+impl<T: std::fmt::Debug> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+ const fn foo(&self) {}
+}
+
+impl<T: std::fmt::Debug + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+ const fn foo2(&self) {}
+}
+
+impl<T: Sync + Sized> Foo<T> {
+//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
+ const fn foo3(&self) {}
+}
+
+struct AlanTuring<T>(T);
+const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+//~^ ERROR `impl Trait` in const fn is unstable
+const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+//~^ ERROR trait bounds other than `Sized`
+const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_unsafe() { unsafe {} }
+
+const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+//~^ ERROR trait bounds other than `Sized`
+
+const fn no_fn_ptrs(_x: fn()) {}
+//~^ ERROR function pointers in const fn are unstable
+const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+//~^ ERROR function pointers in const fn are unstable
+
--- /dev/null
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:49:25
+ |
+LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:51:5
+ |
+LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:56:28
+ |
+LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:58:5
+ |
+LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/min_const_fn.rs:63:27
+ |
+LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+ | ^^^^ constant functions cannot evaluate destructors
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:65:5
+ |
+LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:70:5
+ |
+LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:88:16
+ |
+LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:90:18
+ |
+LL | const fn foo11_2<T: Send>(t: T) -> T { t }
+ | ^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:92:33
+ |
+LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
+ | ^^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:94:35
+ |
+LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
+ | ^^^^^^^
+
+error: only int and `bool` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:96:35
+ |
+LL | const fn foo19_3(f: f32) -> f32 { -f }
+ | ^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn.rs:98:43
+ |
+LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
+ | ^^^^^
+
+error: cannot access `static` items in const fn
+ --> $DIR/min_const_fn.rs:102:27
+ |
+LL | const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
+ | ^^^
+
+error: cannot access `static` items in const fn
+ --> $DIR/min_const_fn.rs:103:36
+ |
+LL | const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
+ | ^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:104:42
+ |
+LL | const fn foo30(x: *const u32) -> usize { x as usize }
+ | ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:106:42
+ |
+LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
+ | ^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:108:38
+ |
+LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:110:29
+ |
+LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
+ | ^^^^^^^^^^^
+
+error: local variables in const fn are unstable
+ --> $DIR/min_const_fn.rs:111:34
+ |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn are unstable
+ | ^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:112:44
+ |
+LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
+ | ^^^^^^
+
+error: `if`, `match`, `&&` and `||` are not stable in const fn
+ --> $DIR/min_const_fn.rs:114:44
+ |
+LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
+ | ^^^^^^
+
+error: mutable references in const fn are unstable
+ --> $DIR/min_const_fn.rs:116:14
+ |
+LL | const fn inc(x: &mut i32) { *x += 1 }
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:121:6
+ |
+LL | impl<T: std::fmt::Debug> Foo<T> {
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:126:6
+ |
+LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
+ | ^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:131:6
+ |
+LL | impl<T: Sync + Sized> Foo<T> {
+ | ^
+
+error: `impl Trait` in const fn is unstable
+ --> $DIR/min_const_fn.rs:137:1
+ |
+LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:139:34
+ |
+LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:141:22
+ |
+LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: `impl Trait` in const fn is unstable
+ --> $DIR/min_const_fn.rs:142:1
+ |
+LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:143:23
+ |
+LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
+ | ^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:144:1
+ |
+LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn.rs:149:41
+ |
+LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn.rs:152:21
+ |
+LL | const fn no_fn_ptrs(_x: fn()) {}
+ | ^^
+
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn.rs:154:1
+ |
+LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 35 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
--- /dev/null
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn_dyn.rs:21:5
+ |
+LL | x.0.field;
+ | ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn_dyn.rs:24:66
+ |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+ | ^^
+
+error[E0597]: borrowed value does not live long enough
+ --> $DIR/min_const_fn_dyn.rs:24:67
+ |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+ | ^ - temporary value only lives until here
+ | |
+ | temporary value does not live long enough
+ |
+ = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasDyn {
+ field: &'static dyn std::fmt::Debug,
+}
+
+struct Hide(HasDyn);
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+ x.0.field;
+//~^ ERROR trait bounds other than `Sized`
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+//~^ ERROR trait bounds other than `Sized`
+
+fn main() {}
--- /dev/null
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn_dyn.rs:21:5
+ |
+LL | x.0.field;
+ | ^^^^^^^^^
+
+error: trait bounds other than `Sized` on const fn parameters are unstable
+ --> $DIR/min_const_fn_dyn.rs:24:66
+ |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
+ | ^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+struct HasPtr {
+ field: fn(),
+}
+
+struct Hide(HasPtr);
+
+fn field() {}
+
+const fn no_inner_dyn_trait(_x: Hide) {}
+const fn no_inner_dyn_trait2(x: Hide) {
+ x.0.field;
+//~^ ERROR function pointers in const fn
+}
+const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+//~^ ERROR function pointers in const fn
+
+fn main() {}
--- /dev/null
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn_fn_ptr.rs:23:5
+ |
+LL | x.0.field;
+ | ^^^^^^^^^
+
+error: function pointers in const fn are unstable
+ --> $DIR/min_const_fn_fn_ptr.rs:26:59
+ |
+LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
+ | ^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "humans",
+ reason = "who ever let humans program computers,
+ we're apparently really bad at it",
+ issue = "0")]
+
+#![feature(rustc_const_unstable, const_fn, foo)]
+#![feature(staged_api)]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature="foo")]
+const fn foo() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+
+#[unstable(feature = "rust1", issue="0")]
+const fn foo2() -> u32 { 42 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// can't call non-min_const_fn
+const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+
+#[stable(feature = "rust1", since = "1.0.0")]
+// conformity is required, even with `const_fn` feature gate
+const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+
+fn main() {}
--- /dev/null
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_fn_libstd_stability.rs:25:25
+ |
+LL | const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^
+
+error: can only call other `min_const_fn` within a `min_const_fn`
+ --> $DIR/min_const_fn_libstd_stability.rs:32:26
+ |
+LL | const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
+ | ^^^^^^
+
+error: only int, `bool` and `char` operations are stable in const fn
+ --> $DIR/min_const_fn_libstd_stability.rs:36:26
+ |
+LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(min_const_fn)]
+
+// ok
+const unsafe fn foo4() -> i32 { 42 }
+const unsafe fn foo5<T>() -> *const T { 0 as *const T }
+const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
+const fn no_unsafe() { unsafe {} }
+
+// not ok
+const fn foo8() -> i32 {
+ unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo9() -> *const String {
+ unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+}
+const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
+ unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+}
+const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+//~^ dereferencing raw pointers in constant functions
+
+fn main() {}
+
+const unsafe fn no_union() {
+ union Foo { x: (), y: () }
+ Foo { x: () }.y //~ ERROR not allowed in const fn
+ //~^ unions in const fn
+}
--- /dev/null
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+ --> $DIR/min_const_fn_unsafe.rs:29:51
+ |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+ | ^^
+ |
+ = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
+
+error[E0658]: unions in const fn are unstable (see issue #51909)
+ --> $DIR/min_const_fn_unsafe.rs:36:5
+ |
+LL | Foo { x: () }.y //~ ERROR not allowed in const fn
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(const_fn_union)] to the crate attributes to enable
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+ --> $DIR/min_const_fn_unsafe.rs:21:14
+ |
+LL | unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+ --> $DIR/min_const_fn_unsafe.rs:24:14
+ |
+LL | unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+ | ^^^^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+ --> $DIR/min_const_fn_unsafe.rs:27:14
+ |
+LL | unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
+ --> $DIR/min_const_fn_unsafe.rs:29:51
+ |
+LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: access to union field is unsafe and unsafe operations are not allowed in const fn
+ --> $DIR/min_const_fn_unsafe.rs:36:5
+ |
+LL | Foo { x: () }.y //~ ERROR not allowed in const fn
+ | ^^^^^^^^^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
LL | fn size_of<T>(); //~ ERROR E0308
| ^^^^^^^^^^^^^^^^ expected (), found usize
|
- = note: expected type `unsafe extern "rust-intrinsic" fn()`
- found type `unsafe extern "rust-intrinsic" fn() -> usize`
+ = note: expected type `extern "rust-intrinsic" fn()`
+ found type `extern "rust-intrinsic" fn() -> usize`
error: aborting due to previous error
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test use of const fn without feature gate.
+// Test use of const fn without the `const_fn` feature gate.
+// `min_const_fn` is checked in its own file
+#![feature(min_const_fn)]
-const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+const fn foo() -> usize { 0 } // ok
trait Foo {
const fn foo() -> u32; //~ ERROR const fn is unstable
}
impl Foo {
- const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+ const fn baz() -> u32 { 0 } // ok
}
impl Foo for u32 {
- const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
- //~| ERROR trait fns cannot be declared const
+ const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
}
static FOO: usize = foo();
error[E0379]: trait fns cannot be declared const
- --> $DIR/feature-gate-const_fn.rs:16:5
+ --> $DIR/feature-gate-const_fn.rs:18:5
|
LL | const fn foo() -> u32; //~ ERROR const fn is unstable
| ^^^^^ trait fns cannot be const
error[E0379]: trait fns cannot be declared const
- --> $DIR/feature-gate-const_fn.rs:18:5
+ --> $DIR/feature-gate-const_fn.rs:20:5
|
LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
| ^^^^^ trait fns cannot be const
error[E0379]: trait fns cannot be declared const
- --> $DIR/feature-gate-const_fn.rs:27:5
+ --> $DIR/feature-gate-const_fn.rs:29:5
|
-LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+LL | const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
| ^^^^^ trait fns cannot be const
error[E0658]: const fn is unstable (see issue #24111)
- --> $DIR/feature-gate-const_fn.rs:13:1
- |
-LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
- --> $DIR/feature-gate-const_fn.rs:16:5
+ --> $DIR/feature-gate-const_fn.rs:18:5
|
LL | const fn foo() -> u32; //~ ERROR const fn is unstable
| ^^^^^^^^^^^^^^^^^^^^^^
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0658]: const fn is unstable (see issue #24111)
- --> $DIR/feature-gate-const_fn.rs:18:5
+ --> $DIR/feature-gate-const_fn.rs:20:5
|
LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error[E0658]: const fn is unstable (see issue #24111)
- --> $DIR/feature-gate-const_fn.rs:23:5
- |
-LL | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error[E0658]: const fn is unstable (see issue #24111)
- --> $DIR/feature-gate-const_fn.rs:27:5
- |
-LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_fn)] to the crate attributes to enable
-
-error: aborting due to 8 previous errors
+error: aborting due to 5 previous errors
Some errors occurred: E0379, E0658.
For more information about an error, try `rustc --explain E0379`.
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of min_const_fn without feature gate.
+
+const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+
+trait Foo {
+ const fn foo() -> u32; //~ ERROR const fn is unstable
+ //~| ERROR trait fns cannot be declared const
+ const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+ //~| ERROR trait fns cannot be declared const
+}
+
+impl Foo {
+ const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+}
+
+impl Foo for u32 {
+ const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+ //~| ERROR trait fns cannot be declared const
+}
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+ ($n:ident: $t:ty = $v:expr) => {
+ const $n: $t = $v;
+ }
+}
+
+constant! {
+ BAZ: usize = foo()
+}
+
+fn main() {
+ let x: [usize; foo()] = [];
+}
--- /dev/null
+error[E0379]: trait fns cannot be declared const
+ --> $DIR/feature-gate-min_const_fn.rs:16:5
+ |
+LL | const fn foo() -> u32; //~ ERROR const fn is unstable
+ | ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+ --> $DIR/feature-gate-min_const_fn.rs:18:5
+ |
+LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+ | ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+ --> $DIR/feature-gate-min_const_fn.rs:27:5
+ |
+LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+ | ^^^^^ trait fns cannot be const
+
+error[E0658]: const fn is unstable (see issue #53555)
+ --> $DIR/feature-gate-min_const_fn.rs:13:1
+ |
+LL | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+ --> $DIR/feature-gate-min_const_fn.rs:16:5
+ |
+LL | const fn foo() -> u32; //~ ERROR const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #24111)
+ --> $DIR/feature-gate-min_const_fn.rs:18:5
+ |
+LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+ --> $DIR/feature-gate-min_const_fn.rs:23:5
+ |
+LL | const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error[E0658]: const fn is unstable (see issue #53555)
+ --> $DIR/feature-gate-min_const_fn.rs:27:5
+ |
+LL | const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(min_const_fn)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
+Some errors occurred: E0379, E0658.
+For more information about an error, try `rustc --explain E0379`.