Skip to content

Commit 59dcba5

Browse files
committed
Auto merge of #21610 - sfackler:debug-lint, r=alexcrichton
Closes #20855 r? @alexcrichton
2 parents 7615e18 + 7021491 commit 59dcba5

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

src/libcore/fmt/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ pub trait Show {
245245
#[unstable = "I/O and core have yet to be reconciled"]
246246
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is defined in your \
247247
crate, add `#[derive(Debug)]` or manually implement it"]
248+
#[lang = "debug_trait"]
248249
pub trait Debug {
249250
/// Formats the value using the given formatter.
250251
fn fmt(&self, &mut Formatter) -> Result;

src/librustc/lint/builtin.rs

+63
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,69 @@ impl LintPass for MissingCopyImplementations {
16271627
}
16281628
}
16291629

1630+
declare_lint! {
1631+
MISSING_DEBUG_IMPLEMENTATIONS,
1632+
Allow,
1633+
"detects missing implementations of fmt::Debug"
1634+
}
1635+
1636+
pub struct MissingDebugImplementations {
1637+
impling_types: Option<NodeSet>,
1638+
}
1639+
1640+
impl MissingDebugImplementations {
1641+
pub fn new() -> MissingDebugImplementations {
1642+
MissingDebugImplementations {
1643+
impling_types: None,
1644+
}
1645+
}
1646+
}
1647+
1648+
impl LintPass for MissingDebugImplementations {
1649+
fn get_lints(&self) -> LintArray {
1650+
lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
1651+
}
1652+
1653+
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
1654+
if !cx.exported_items.contains(&item.id) {
1655+
return;
1656+
}
1657+
1658+
match item.node {
1659+
ast::ItemStruct(..) | ast::ItemEnum(..) => {},
1660+
_ => return,
1661+
}
1662+
1663+
let debug = match cx.tcx.lang_items.debug_trait() {
1664+
Some(debug) => debug,
1665+
None => return,
1666+
};
1667+
1668+
if self.impling_types.is_none() {
1669+
let impls = cx.tcx.trait_impls.borrow();
1670+
let impls = match impls.get(&debug) {
1671+
Some(impls) => {
1672+
impls.borrow().iter()
1673+
.filter(|d| d.krate == ast::LOCAL_CRATE)
1674+
.filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
1675+
.map(|d| d.node)
1676+
.collect()
1677+
}
1678+
None => NodeSet(),
1679+
};
1680+
self.impling_types = Some(impls);
1681+
debug!("{:?}", self.impling_types);
1682+
}
1683+
1684+
if !self.impling_types.as_ref().unwrap().contains(&item.id) {
1685+
cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS,
1686+
item.span,
1687+
"type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \
1688+
or a manual implementation")
1689+
}
1690+
}
1691+
}
1692+
16301693
declare_lint! {
16311694
DEPRECATED,
16321695
Warn,

src/librustc/lint/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ impl LintStore {
219219
RawPointerDerive,
220220
MissingDoc,
221221
Stability,
222+
MissingDebugImplementations,
222223
);
223224

224225
add_lint_group!(sess, "bad_style",

src/librustc/middle/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,6 @@ lets_do_this! {
328328
IteratorItem, "iterator", iterator;
329329

330330
StackExhaustedLangItem, "stack_exhausted", stack_exhausted;
331+
332+
DebugTraitLangItem, "debug_trait", debug_trait;
331333
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: --crate-type lib
12+
#![deny(missing_debug_implementations)]
13+
#![allow(unused, unstable, missing_copy_implementations)]
14+
15+
use std::fmt;
16+
17+
pub enum A {} //~ ERROR type does not implement `fmt::Debug`
18+
19+
#[derive(Debug)]
20+
pub enum B {}
21+
22+
pub enum C {}
23+
24+
impl fmt::Debug for C {
25+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
26+
Ok(())
27+
}
28+
}
29+
30+
pub struct Foo; //~ ERROR type does not implement `fmt::Debug`
31+
32+
#[derive(Debug)]
33+
pub struct Bar;
34+
35+
pub struct Baz;
36+
37+
impl fmt::Debug for Baz {
38+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
39+
Ok(())
40+
}
41+
}
42+
43+
struct PrivateStruct;
44+
45+
enum PrivateEnum {}
46+
47+
#[derive(Debug)]
48+
struct GenericType<T>(T);

0 commit comments

Comments
 (0)