}
// only some unsafety is allowed in const fn
if self.min_const_fn {
+ let min_const_unsafe_fn = self.tcx.features().min_const_unsafe_fn;
for violation in violations {
match violation.kind {
- // these are allowed
- UnsafetyViolationKind::GatedConstFnCall => {
+ UnsafetyViolationKind::GatedConstFnCall if min_const_unsafe_fn => {
+ // these function calls to unsafe functions are allowed
// if `#![feature(min_const_unsafe_fn)]` is active
- if !self.tcx.sess.features_untracked().min_const_unsafe_fn {
- if !self.violations.contains(&violation) {
- self.violations.push(violation.clone())
- }
+ },
+ UnsafetyViolationKind::GatedConstFnCall => {
+ // without the feature gate, we report errors
+ if !self.violations.contains(&violation) {
+ self.violations.push(violation.clone())
}
}
// these unsafe things are stable in const fn
UnsafetyViolationKind::GeneralAndConstFn => {},
+ // these things are forbidden in const fns
UnsafetyViolationKind::General |
UnsafetyViolationKind::BorrowPacked(_) |
UnsafetyViolationKind::ExternStatic(_) => {
unsafe_blocks: &'a mut Vec<(ast::NodeId, bool)>)
{
let body_id =
- tcx.hir.as_local_node_id(def_id).and_then(|node_id| {
- tcx.hir.maybe_body_owned_by(node_id)
+ tcx.hir().as_local_node_id(def_id).and_then(|node_id| {
+ tcx.hir().maybe_body_owned_by(node_id)
});
let body_id = match body_id {
return
}
};
- let body = tcx.hir.body(body_id);
+ let body = tcx.hir().body(body_id);
debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})",
def_id, body, used_unsafe);
{
debug!("unsafety_violations({:?})", def_id);
- // NB: this borrow is valid because all the consumers of
+ // N.B., this borrow is valid because all the consumers of
// `mir_built` force this.
let mir = &tcx.mir_built(def_id).borrow();
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),
+ tcx.is_min_const_fn(def_id),
mir, source_scope_local_data, tcx, param_env);
checker.visit_mir(mir);
}
fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
- let lint_node_id = match tcx.hir.as_local_node_id(def_id) {
+ let lint_node_id = match tcx.hir().as_local_node_id(def_id) {
Some(node_id) => node_id,
None => bug!("checking unsafety for non-local def id {:?}", def_id)
};
fn is_enclosed(tcx: TyCtxt,
used_unsafe: &FxHashSet<ast::NodeId>,
id: ast::NodeId) -> Option<(String, ast::NodeId)> {
- let parent_id = tcx.hir.get_parent_node(id);
+ let parent_id = tcx.hir().get_parent_node(id);
if parent_id != id {
if used_unsafe.contains(&parent_id) {
Some(("block".to_string(), parent_id))
} else if let Some(Node::Item(&hir::Item {
node: hir::ItemKind::Fn(_, header, _, _),
..
- })) = tcx.hir.find(parent_id) {
+ })) = tcx.hir().find(parent_id) {
match header.unsafety {
hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
hir::Unsafety::Normal => None,
}
fn report_unused_unsafe(tcx: TyCtxt, used_unsafe: &FxHashSet<ast::NodeId>, id: ast::NodeId) {
- let span = tcx.sess.source_map().def_span(tcx.hir.span(id));
+ let span = tcx.sess.source_map().def_span(tcx.hir().span(id));
let msg = "unnecessary `unsafe` block";
let mut db = tcx.struct_span_lint_node(UNUSED_UNSAFE, id, span, msg);
db.span_label(span, msg);
if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) {
- db.span_label(tcx.sess.source_map().def_span(tcx.hir.span(id)),
+ db.span_label(tcx.sess.source_map().def_span(tcx.hir().span(id)),
format!("because it's nested under this `unsafe` {}", kind));
}
db.emit();
// Report an error.
match kind {
UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
- tcx.sess.struct_span_err(
+ let mut err = 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();
+ are not allowed in const fn", description));
+ err.span_label(source_info.span, &description.as_str()[..])
+ .note(&details.as_str()[..]);
+ if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
+ err.note(
+ "unsafe action within a `const unsafe fn` still require an `unsafe` \
+ block in contrast to regular `unsafe fn`."
+ );
+ }
+ err.emit();
}
UnsafetyViolationKind::GeneralAndConstFn |
UnsafetyViolationKind::General => {