Skip to content

Make unconditional_recursion work across function boundaries #75067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
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
14 changes: 12 additions & 2 deletions src/librustc_middle/query/mod.rs
Original file line number Diff line number Diff line change
@@ -221,6 +221,16 @@ rustc_queries! {
}
}

/// Finds call targets in `key`s MIR body that are guaranteed to be called when the function
/// is entered.
query inevitable_calls(key: DefId) -> &'tcx [(DefId, SubstsRef<'tcx>, &'tcx [Span])] {
desc {
|tcx| "computing call targets of `{}`",
tcx.def_path_str(key),
}
no_hash
}

/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
query mir_built(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
@@ -233,7 +243,7 @@ rustc_queries! {
/// See the README for the `mir` module for details.
query mir_const(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
desc {
|tcx| "processing MIR for {}`{}`",
|tcx| "const-processing MIR for {}`{}`",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
@@ -254,7 +264,7 @@ rustc_queries! {
) {
no_hash
desc {
|tcx| "processing {}`{}`",
|tcx| "validating MIR for {}`{}`",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/steal.rs
Original file line number Diff line number Diff line change
@@ -39,6 +39,6 @@ impl<T> Steal<T> {
pub fn steal(&self) -> T {
let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
let value = value_ref.take();
value.expect("attempt to read from stolen value")
value.expect("attempt to steal stolen value again")
}
}
2 changes: 2 additions & 0 deletions src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ mod borrow_check;
pub mod const_eval;
pub mod dataflow;
pub mod interpret;
mod lints;
pub mod monomorphize;
mod shim;
pub mod transform;
@@ -59,4 +60,5 @@ pub fn provide(providers: &mut Providers) {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::destructure_const(tcx, param_env, value)
};
providers.inevitable_calls = lints::inevitable_calls;
}
452 changes: 452 additions & 0 deletions src/librustc_mir/lints.rs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/librustc_mir/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -285,6 +285,10 @@ fn mir_const<'tcx>(
tcx.ensure().unsafety_check_result(def.did);
}

// Ensure that `inevitable_calls` is computed before stealing the MIR as it is used by MIR
// lints.
let _ = tcx.inevitable_calls(def.did.to_def_id());

let mut body = tcx.mir_built(def).steal();

util::dump_mir(
@@ -297,6 +301,8 @@ fn mir_const<'tcx>(
|_, _| Ok(()),
);

crate::lints::check(tcx, def.did);

run_passes(
tcx,
&mut body,
4 changes: 0 additions & 4 deletions src/librustc_mir_build/build/mod.rs
Original file line number Diff line number Diff line change
@@ -19,8 +19,6 @@ use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_target::spec::PanicStrategy;

use super::lints;

crate fn mir_built<'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
@@ -200,8 +198,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
build::construct_const(cx, body_id, return_ty, return_ty_span)
};

lints::check(tcx, &body, def.did);

// The borrow checker will replace all the regions here with its own
// inference variables. There's no point having non-erased regions here.
// The exception is `body.user_type_annotations`, which is used unmodified
1 change: 0 additions & 1 deletion src/librustc_mir_build/lib.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,6 @@ extern crate tracing;
extern crate rustc_middle;

mod build;
mod lints;
mod thir;

use rustc_middle::ty::query::Providers;
2 changes: 2 additions & 0 deletions src/test/ui/consts/uninhabited-const-issue-61744.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// build-fail

#![allow(unconditional_recursion)]

pub const unsafe fn fake_type<T>() -> T {
hint_unreachable()
}
262 changes: 131 additions & 131 deletions src/test/ui/consts/uninhabited-const-issue-61744.stderr

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/test/ui/impl-trait/auto-trait-leak.stderr
Original file line number Diff line number Diff line change
@@ -9,12 +9,12 @@ note: ...which requires borrow-checking `cycle1`...
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `cycle1`...
note: ...which requires validating MIR for `cycle1`...
--> $DIR/auto-trait-leak.rs:12:1
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `cycle1`...
note: ...which requires const-processing MIR for `cycle1`...
--> $DIR/auto-trait-leak.rs:12:1
|
LL | fn cycle1() -> impl Clone {
@@ -45,12 +45,12 @@ note: ...which requires borrow-checking `cycle2`...
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `cycle2`...
note: ...which requires validating MIR for `cycle2`...
--> $DIR/auto-trait-leak.rs:20:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `cycle2`...
note: ...which requires const-processing MIR for `cycle2`...
--> $DIR/auto-trait-leak.rs:20:1
|
LL | fn cycle2() -> impl Clone {
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
//
// Regression test for #38064.

#![allow(unconditional_recursion)]

trait Quux {}

fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-impl-trait-issue-38064.rs:8:13
--> $DIR/infinite-impl-trait-issue-38064.rs:10:13
|
LL | fn foo() -> impl Quux {
| ^^^^^^^^^ recursive opaque type
@@ -11,7 +11,7 @@ LL | fn bar() -> impl Quux {
| --------- returning this opaque type `foo::Foo<impl Quux>`

error[E0720]: cannot resolve opaque type
--> $DIR/infinite-impl-trait-issue-38064.rs:14:13
--> $DIR/infinite-impl-trait-issue-38064.rs:16:13
|
LL | fn foo() -> impl Quux {
| --------- returning this opaque type `bar::Bar<impl Quux>`
Original file line number Diff line number Diff line change
@@ -89,7 +89,6 @@ fn mutual_recursion() -> impl Sync {
}

fn mutual_recursion_b() -> impl Sized {
//~^ ERROR
mutual_recursion()
}

61 changes: 41 additions & 20 deletions src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
Original file line number Diff line number Diff line change
@@ -119,30 +119,51 @@ LL | | x;
LL | | }
| |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:86:26
error[E0391]: cycle detected when building MIR for `mutual_recursion`
--> $DIR/recursive-impl-trait-type-indirect.rs:86:1
|
LL | fn mutual_recursion() -> impl Sync {
| ^^^^^^^^^ recursive opaque type
LL |
LL | mutual_recursion_b()
| -------------------- returning here with type `impl Sized`
...
LL | fn mutual_recursion_b() -> impl Sized {
| ---------- returning this opaque type `impl Sized`

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:91:28
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires type-checking `mutual_recursion`...
--> $DIR/recursive-impl-trait-type-indirect.rs:86:1
|
LL | fn mutual_recursion() -> impl Sync {
| --------- returning this opaque type `impl std::marker::Sync`
...
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires evaluating trait selection obligation `impl Sized: std::marker::Sync`...
note: ...which requires computing type of `mutual_recursion_b::{{opaque}}#0`...
--> $DIR/recursive-impl-trait-type-indirect.rs:91:28
|
LL | fn mutual_recursion_b() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | mutual_recursion()
| ------------------ returning here with type `impl std::marker::Sync`
| ^^^^^^^^^^
note: ...which requires borrow-checking `mutual_recursion_b`...
--> $DIR/recursive-impl-trait-type-indirect.rs:91:1
|
LL | fn mutual_recursion_b() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires validating MIR for `mutual_recursion_b`...
--> $DIR/recursive-impl-trait-type-indirect.rs:91:1
|
LL | fn mutual_recursion_b() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-processing MIR for `mutual_recursion_b`...
--> $DIR/recursive-impl-trait-type-indirect.rs:91:1
|
LL | fn mutual_recursion_b() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires computing call targets of `mutual_recursion`...
--> $DIR/recursive-impl-trait-type-indirect.rs:86:1
|
LL | fn mutual_recursion() -> impl Sync {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires building MIR for `mutual_recursion`, completing the cycle
note: cycle used when unsafety-checking `mutual_recursion`
--> $DIR/recursive-impl-trait-type-indirect.rs:86:1
|
LL | fn mutual_recursion() -> impl Sync {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 14 previous errors
error: aborting due to 13 previous errors

For more information about this error, try `rustc --explain E0720`.
Some errors have detailed explanations: E0391, E0720.
For more information about an error, try `rustc --explain E0391`.
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@
// otherwise forbidden. Even when there's an opaque type in another crate
// hiding this.

#![allow(unconditional_recursion)]

fn id<T>(t: T) -> impl Sized { t }

fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:9:22
|
LL | fn id<T>(t: T) -> impl Sized { t }
| ---------- returning this opaque type `impl Sized`
@@ -10,7 +10,7 @@ LL | id(recursive_id2())
| ------------------- returning here with type `impl Sized`

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:13:23
|
LL | fn id<T>(t: T) -> impl Sized { t }
| ---------- returning this opaque type `impl Sized`
@@ -21,7 +21,7 @@ LL | id(recursive_id())
| ------------------ returning here with type `impl Sized`

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:19:24
|
LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
| ---------- returning this opaque type `impl Sized`
@@ -32,7 +32,7 @@ LL | wrap(recursive_wrap2())
| ----------------------- returning here with type `impl Sized`

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
--> $DIR/recursive-impl-trait-type-through-non-recursive.rs:23:25
|
LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
| ---------- returning this opaque type `impl Sized`
2 changes: 2 additions & 0 deletions src/test/ui/infinite/infinite-recursion-const-fn.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//https://github.com/rust-lang/rust/issues/31364

#![allow(unconditional_recursion)]

const fn a() -> usize { b() } //~ ERROR cycle detected when const-evaluating `a` [E0391]
const fn b() -> usize { a() }
const ARR: [i32; a()] = [5; 6];
6 changes: 3 additions & 3 deletions src/test/ui/infinite/infinite-recursion-const-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error[E0391]: cycle detected when const-evaluating `a`
--> $DIR/infinite-recursion-const-fn.rs:3:1
--> $DIR/infinite-recursion-const-fn.rs:5:1
|
LL | const fn a() -> usize { b() }
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `b`...
--> $DIR/infinite-recursion-const-fn.rs:4:1
--> $DIR/infinite-recursion-const-fn.rs:6:1
|
LL | const fn b() -> usize { a() }
| ^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires const-evaluating `a`, completing the cycle
note: cycle used when const-evaluating `ARR::{{constant}}#0`
--> $DIR/infinite-recursion-const-fn.rs:5:18
--> $DIR/infinite-recursion-const-fn.rs:7:18
|
LL | const ARR: [i32; a()] = [5; 6];
| ^^^
1 change: 1 addition & 0 deletions src/test/ui/lint/dead-code/lint-dead-code-1.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(unconditional_recursion)]
#![deny(dead_code)]

#![crate_type="lib"]
22 changes: 11 additions & 11 deletions src/test/ui/lint/dead-code/lint-dead-code-1.stderr
Original file line number Diff line number Diff line change
@@ -1,65 +1,65 @@
error: struct is never constructed: `Bar`
--> $DIR/lint-dead-code-1.rs:12:16
--> $DIR/lint-dead-code-1.rs:13:16
|
LL | pub struct Bar;
| ^^^
|
note: the lint level is defined here
--> $DIR/lint-dead-code-1.rs:5:9
--> $DIR/lint-dead-code-1.rs:6:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^

error: static is never used: `priv_static`
--> $DIR/lint-dead-code-1.rs:20:1
--> $DIR/lint-dead-code-1.rs:21:1
|
LL | static priv_static: isize = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: constant is never used: `priv_const`
--> $DIR/lint-dead-code-1.rs:27:1
--> $DIR/lint-dead-code-1.rs:28:1
|
LL | const priv_const: isize = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: struct is never constructed: `PrivStruct`
--> $DIR/lint-dead-code-1.rs:35:8
--> $DIR/lint-dead-code-1.rs:36:8
|
LL | struct PrivStruct;
| ^^^^^^^^^^

error: enum is never used: `priv_enum`
--> $DIR/lint-dead-code-1.rs:64:6
--> $DIR/lint-dead-code-1.rs:65:6
|
LL | enum priv_enum { foo2, bar2 }
| ^^^^^^^^^

error: variant is never constructed: `bar3`
--> $DIR/lint-dead-code-1.rs:67:5
--> $DIR/lint-dead-code-1.rs:68:5
|
LL | bar3
| ^^^^

error: function is never used: `priv_fn`
--> $DIR/lint-dead-code-1.rs:88:4
--> $DIR/lint-dead-code-1.rs:89:4
|
LL | fn priv_fn() {
| ^^^^^^^

error: function is never used: `foo`
--> $DIR/lint-dead-code-1.rs:93:4
--> $DIR/lint-dead-code-1.rs:94:4
|
LL | fn foo() {
| ^^^

error: function is never used: `bar`
--> $DIR/lint-dead-code-1.rs:98:4
--> $DIR/lint-dead-code-1.rs:99:4
|
LL | fn bar() {
| ^^^

error: function is never used: `baz`
--> $DIR/lint-dead-code-1.rs:102:4
--> $DIR/lint-dead-code-1.rs:103:4
|
LL | fn baz() -> impl Copy {
| ^^^
1 change: 1 addition & 0 deletions src/test/ui/lint/dead-code/lint-dead-code-3.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(clashing_extern_declarations)]
#![allow(unconditional_recursion)]
#![deny(dead_code)]

#![crate_type="lib"]
12 changes: 6 additions & 6 deletions src/test/ui/lint/dead-code/lint-dead-code-3.stderr
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
error: struct is never constructed: `Foo`
--> $DIR/lint-dead-code-3.rs:14:8
--> $DIR/lint-dead-code-3.rs:15:8
|
LL | struct Foo;
| ^^^
|
note: the lint level is defined here
--> $DIR/lint-dead-code-3.rs:4:9
--> $DIR/lint-dead-code-3.rs:5:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^

error: associated function is never used: `foo`
--> $DIR/lint-dead-code-3.rs:16:8
--> $DIR/lint-dead-code-3.rs:17:8
|
LL | fn foo(&self) {
| ^^^

error: function is never used: `bar`
--> $DIR/lint-dead-code-3.rs:21:4
--> $DIR/lint-dead-code-3.rs:22:4
|
LL | fn bar() {
| ^^^

error: enum is never used: `c_void`
--> $DIR/lint-dead-code-3.rs:60:6
--> $DIR/lint-dead-code-3.rs:61:6
|
LL | enum c_void {}
| ^^^^^^

error: function is never used: `free`
--> $DIR/lint-dead-code-3.rs:62:5
--> $DIR/lint-dead-code-3.rs:63:5
|
LL | fn free(p: *const c_void);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
40 changes: 25 additions & 15 deletions src/test/ui/lint/lint-unconditional-recursion.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#![deny(unconditional_recursion)]
#![warn(unconditional_recursion)]

// check-pass

#![allow(dead_code)]
fn foo() { //~ ERROR function cannot return without recursing
fn foo() { //~ WARN function cannot return without recursing
foo();
}

@@ -11,7 +13,7 @@ fn bar() {
}
}

fn baz() { //~ ERROR function cannot return without recursing
fn baz() { //~ WARN function cannot return without recursing
if true {
baz()
} else {
@@ -23,7 +25,7 @@ fn qux() {
loop {}
}

fn quz() -> bool { //~ ERROR function cannot return without recursing
fn quz() -> bool { //~ WARN function cannot return without recursing
if true {
while quz() {}
true
@@ -34,13 +36,13 @@ fn quz() -> bool { //~ ERROR function cannot return without recursing

// Trait method calls.
trait Foo {
fn bar(&self) { //~ ERROR function cannot return without recursing
fn bar(&self) { //~ WARN function cannot return without recursing
self.bar()
}
}

impl Foo for Box<dyn Foo + 'static> {
fn bar(&self) { //~ ERROR function cannot return without recursing
fn bar(&self) { //~ WARN function cannot return without recursing
loop {
self.bar()
}
@@ -49,7 +51,7 @@ impl Foo for Box<dyn Foo + 'static> {

// Trait method call with integer fallback after method resolution.
impl Foo for i32 {
fn bar(&self) { //~ ERROR function cannot return without recursing
fn bar(&self) { //~ WARN function cannot return without recursing
0.bar()
}
}
@@ -62,13 +64,13 @@ impl Foo for u32 {

// Trait method calls via paths.
trait Foo2 {
fn bar(&self) { //~ ERROR function cannot return without recursing
fn bar(&self) { //~ WARN function cannot return without recursing
Foo2::bar(self)
}
}

impl Foo2 for Box<dyn Foo2 + 'static> {
fn bar(&self) { //~ ERROR function cannot return without recursing
fn bar(&self) { //~ WARN function cannot return without recursing
loop {
Foo2::bar(self)
}
@@ -78,19 +80,19 @@ impl Foo2 for Box<dyn Foo2 + 'static> {
struct Baz;
impl Baz {
// Inherent method call.
fn qux(&self) { //~ ERROR function cannot return without recursing
fn qux(&self) { //~ WARN function cannot return without recursing
self.qux();
}

// Inherent method call via path.
fn as_ref(&self) -> &Self { //~ ERROR function cannot return without recursing
fn as_ref(&self) -> &Self { //~ WARN function cannot return without recursing
Baz::as_ref(self)
}
}

// Trait method calls to impls via paths.
impl Default for Baz {
fn default() -> Baz { //~ ERROR function cannot return without recursing
fn default() -> Baz { //~ WARN function cannot return without recursing
let x = Default::default();
x
}
@@ -99,14 +101,14 @@ impl Default for Baz {
// Overloaded operators.
impl std::ops::Deref for Baz {
type Target = ();
fn deref(&self) -> &() { //~ ERROR function cannot return without recursing
fn deref(&self) -> &() { //~ WARN function cannot return without recursing
&**self
}
}

impl std::ops::Index<usize> for Baz {
type Output = Baz;
fn index(&self, x: usize) -> &Baz { //~ ERROR function cannot return without recursing
fn index(&self, x: usize) -> &Baz { //~ WARN function cannot return without recursing
&self[x]
}
}
@@ -115,7 +117,7 @@ impl std::ops::Index<usize> for Baz {
struct Quux;
impl std::ops::Deref for Quux {
type Target = Baz;
fn deref(&self) -> &Baz { //~ ERROR function cannot return without recursing
fn deref(&self) -> &Baz { //~ WARN function cannot return without recursing
self.as_ref()
}
}
@@ -149,4 +151,12 @@ pub fn panics(x: bool) {
}
}

fn cycle1() { //~ WARN function cannot return without recursing
cycle2();
}

fn cycle2() { //~ WARN function cannot return without recursing
cycle1();
}

fn main() {}
92 changes: 62 additions & 30 deletions src/test/ui/lint/lint-unconditional-recursion.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:4:1
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:6:1
|
LL | fn foo() {
| ^^^^^^^^ cannot return without recursing
@@ -9,12 +9,12 @@ LL | foo();
note: the lint level is defined here
--> $DIR/lint-unconditional-recursion.rs:1:9
|
LL | #![deny(unconditional_recursion)]
LL | #![warn(unconditional_recursion)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:14:1
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:16:1
|
LL | fn baz() {
| ^^^^^^^^ cannot return without recursing
@@ -27,8 +27,8 @@ LL | baz()
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:26:1
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:28:1
|
LL | fn quz() -> bool {
| ^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -41,8 +41,8 @@ LL | loop { quz(); }
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:37:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:39:5
|
LL | fn bar(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -51,8 +51,8 @@ LL | self.bar()
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:43:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:45:5
|
LL | fn bar(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -62,8 +62,8 @@ LL | self.bar()
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:52:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:54:5
|
LL | fn bar(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -72,8 +72,8 @@ LL | 0.bar()
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:65:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:67:5
|
LL | fn bar(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -82,8 +82,8 @@ LL | Foo2::bar(self)
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:71:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:73:5
|
LL | fn bar(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -93,8 +93,8 @@ LL | Foo2::bar(self)
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:81:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:83:5
|
LL | fn qux(&self) {
| ^^^^^^^^^^^^^ cannot return without recursing
@@ -103,8 +103,8 @@ LL | self.qux();
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:86:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:88:5
|
LL | fn as_ref(&self) -> &Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -113,8 +113,8 @@ LL | Baz::as_ref(self)
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:93:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:95:5
|
LL | fn default() -> Baz {
| ^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -123,8 +123,8 @@ LL | let x = Default::default();
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:102:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:104:5
|
LL | fn deref(&self) -> &() {
| ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -133,8 +133,8 @@ LL | &**self
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:109:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:111:5
|
LL | fn index(&self, x: usize) -> &Baz {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -143,8 +143,8 @@ LL | &self[x]
|
= help: a `loop` may express intention better if this is on purpose

error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:118:5
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:120:5
|
LL | fn deref(&self) -> &Baz {
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -153,5 +153,37 @@ LL | self.as_ref()
|
= help: a `loop` may express intention better if this is on purpose

error: aborting due to 14 previous errors
warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:154:1
|
LL | fn cycle1() {
| ^^^^^^^^^^^ cannot return without recursing
LL | cycle2();
| -------- call into the next function in the cycle
|
note: next function in the cycle
--> $DIR/lint-unconditional-recursion.rs:158:1
|
LL | fn cycle2() {
| ^^^^^^^^^^^
LL | cycle1();
| -------- call completing the cycle

warning: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:158:1
|
LL | fn cycle2() {
| ^^^^^^^^^^^ cannot return without recursing
LL | cycle1();
| -------- call into the next function in the cycle
|
note: next function in the cycle
--> $DIR/lint-unconditional-recursion.rs:154:1
|
LL | fn cycle1() {
| ^^^^^^^^^^^
LL | cycle2();
| -------- call completing the cycle

warning: 16 warnings emitted