Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.try_structurally_resolve_type(expr.span, ty).is_never()
&& self.expr_guaranteed_to_constitute_read_for_never(expr)
{
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
let diverges = if self.tcx.is_expanded_by(expr.span, sym::todo_macro) {
// We don't warn for `todo!()` that diverges to avoid flooding the
// user with warnings while they are still working on their code.
Diverges::WarnedAlways
} else {
Diverges::always(expr.span)
};
self.diverges.set(self.diverges.get() | diverges);
}

// Record the type, which applies it effects.
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,21 @@ impl<'tcx> TyCtxt<'tcx> {
None => Err(VarError::NotPresent),
}
}

/// Returns whether this context was expanded by the macro with the given name.
pub fn is_expanded_by(self, span: Span, mac: Symbol) -> bool {
let mut ctxt = span.ctxt();
while !ctxt.is_root() {
let data = ctxt.outer_expn_data();
if let Some(def_id) = data.macro_def_id
&& self.is_diagnostic_item(mac, def_id)
{
return true;
}
ctxt = data.call_site.ctxt();
}
false
}
}

impl<'tcx> TyCtxtAt<'tcx> {
Expand Down
5 changes: 4 additions & 1 deletion library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,10 @@ macro_rules! unimplemented {
/// an intent of implementing the functionality later and the message is "not yet
/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
///
/// Also, some IDEs will mark `todo!`s.
/// Also, some IDEs will mark `todo!`s. Furthermore, the `unreachable_code` lint will
/// not warn on code that is unreachable because of a `todo!()` to reduce unhelpful
/// messages. The code will however still be marked as unreachable, which may have an
/// effect on type and lifetime checks.
///
/// # Panics
///
Expand Down
41 changes: 41 additions & 0 deletions tests/ui/reachable/todo.rs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit hard to discover, but the right directory for the test is tests/ui/reachable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll move the test under a todo.rs there.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//@ check-pass
//@ edition: 2018

#![allow(unused)]
#![warn(unreachable_code)]

macro_rules! later {
() => { todo!() };
}

fn foo() {
todo!();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a test for when another macro expands to todo!?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! 👍

let this_is_unreachable = 1;
}

fn bar() {
panic!("This is really unreachable");
let really_unreachable = true;
//~^ WARNING: unreachable
}

fn baz() -> bool {
if true {
todo!();
false
} else if todo!() {
true
} else {
later!();
false
}
}

fn main() {
foo();
bar();
if baz() {
todo!();
}
let this_is_reachable = 1;
}
16 changes: 16 additions & 0 deletions tests/ui/reachable/todo.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
warning: unreachable statement
--> $DIR/todo.rs:18:5
|
LL | panic!("This is really unreachable");
| ------------------------------------ any code following this expression is unreachable
LL | let really_unreachable = true;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
|
note: the lint level is defined here
--> $DIR/todo.rs:5:9
|
LL | #![warn(unreachable_code)]
| ^^^^^^^^^^^^^^^^

warning: 1 warning emitted

Loading