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.
This commit is contained in:
Huon Wilson 2015-06-29 15:56:00 -07:00
parent b1931e48a0
commit 900af2c6d9
2 changed files with 16 additions and 0 deletions

View File

@ -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()
}

View File

@ -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() {}