about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2015-06-29 15:56:00 -0700
committerHuon Wilson <dbau.pp+github@gmail.com>2015-06-29 16:00:54 -0700
commit900af2c6d9b21ca1b1db35b7b09b0fb59cf78b84 (patch)
tree950dd34f3e2171a26f64072976d5d57ab43e7562
parentb1931e48a01b418b4b1ba6c747f2c99a5b10d96f (diff)
downloadrust-900af2c6d9b21ca1b1db35b7b09b0fb59cf78b84.tar.gz
rust-900af2c6d9b21ca1b1db35b7b09b0fb59cf78b84.zip
lint: default methods must be called on Self to unconditionally recur.
This catches the case when a trait defines a default method that calls
itself, but on a type that isn't necessarily `Self`, e.g. there's no
reason that `T = Self` in the following, so the call isn't necessarily
recursive (`T` may override the call).

    trait Bar {
        fn method<T: Bar>(&self, x: &T) {
            x.method(x)
        }
    }

Fixes #26333.
-rw-r--r--src/librustc_lint/builtin.rs9
-rw-r--r--src/test/compile-fail/lint-unconditional-recursion.rs7
2 files changed, 16 insertions, 0 deletions
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 3d5eb422b63..190e2965e76 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -2007,6 +2007,15 @@ impl LintPass for UnconditionalRecursion {
                     // method instead.
                     ty::MethodTypeParam(
                         ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
+
+                        let on_self = m.substs.self_ty().map_or(false, |t| t.is_self());
+                        if !on_self {
+                            // we can only be recurring in a default
+                            // method if we're being called literally
+                            // on the `Self` type.
+                            return false
+                        }
+
                         tcx.trait_item(trait_ref.def_id, method_num).def_id()
                     }
 
diff --git a/src/test/compile-fail/lint-unconditional-recursion.rs b/src/test/compile-fail/lint-unconditional-recursion.rs
index 0cd71aebd63..47bb7f948a7 100644
--- a/src/test/compile-fail/lint-unconditional-recursion.rs
+++ b/src/test/compile-fail/lint-unconditional-recursion.rs
@@ -67,4 +67,11 @@ fn all_fine() {
     let _f = all_fine;
 }
 
+// issue 26333
+trait Bar {
+    fn method<T: Bar>(&self, x: &T) {
+        x.method(x)
+    }
+}
+
 fn main() {}