@@ -1441,3 +1441,71 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
14411441 }
14421442 }
14431443}
1444+
1445+ /// Lint constants that are erroneous.
1446+ /// Without this lint, we might not get any diagnostic if the constant is
1447+ /// unused within this crate, even though downstream crates can't use it
1448+ /// without producing an error.
1449+ pub struct UnusedBrokenConst;
1450+
1451+ impl LintPass for UnusedBrokenConst {
1452+ fn get_lints(&self) -> LintArray {
1453+ lint_array!()
1454+ }
1455+ }
1456+
1457+ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
1458+ let def_id = cx.tcx.hir.body_owner_def_id(body_id);
1459+ let param_env = cx.tcx.param_env(def_id);
1460+ let cid = ::rustc::mir::interpret::GlobalId {
1461+ instance: ty::Instance::mono(cx.tcx, def_id),
1462+ promoted: None
1463+ };
1464+ if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
1465+ let span = cx.tcx.def_span(def_id);
1466+ let mut diag = cx.struct_span_lint(
1467+ CONST_ERR,
1468+ span,
1469+ &format!("this {} cannot be used", what),
1470+ );
1471+ use rustc::middle::const_val::ConstEvalErrDescription;
1472+ match err.description() {
1473+ ConstEvalErrDescription::Simple(message) => {
1474+ diag.span_label(span, message);
1475+ }
1476+ ConstEvalErrDescription::Backtrace(miri, frames) => {
1477+ diag.span_label(span, format!("{}", miri));
1478+ for frame in frames {
1479+ diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
1480+ }
1481+ }
1482+ }
1483+ diag.emit()
1484+ }
1485+ }
1486+
1487+ struct UnusedBrokenConstVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
1488+
1489+ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UnusedBrokenConstVisitor<'a, 'tcx> {
1490+ fn visit_nested_body(&mut self, id: hir::BodyId) {
1491+ check_const(self.0, id, "array length");
1492+ }
1493+ fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
1494+ hir::intravisit::NestedVisitorMap::None
1495+ }
1496+ }
1497+
1498+ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
1499+ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
1500+ match it.node {
1501+ hir::ItemConst(_, body_id) => {
1502+ check_const(cx, body_id, "constant");
1503+ },
1504+ hir::ItemTy(ref ty, _) => hir::intravisit::walk_ty(
1505+ &mut UnusedBrokenConstVisitor(cx),
1506+ ty
1507+ ),
1508+ _ => {},
1509+ }
1510+ }
1511+ }
0 commit comments