Repository: rust
Issue: Seemingly inconsistent behavior when using default trait parameters
Labels: A-trait-system,T-compiler,C-bug,T-types

I am building a `Length` trait for a `Line` struct that determines the length of a line using various geospatial distance algorithms. It utilizes a default trait parameter to specify a reasonable default to improve the ergonomics. While designing the trait, I noticed some inconsistent behavior.

Consider the next two blocks of code.

- The first has everything parameterized with type `T` which represents a numeric type for the coordinates of the lines and also the return type for the length algorithm.
- The second is the same, but without a parameterized `T`. Instead `f32` is hardcoded everywhere.

A couple questions come up:

1. For the first code block, in the `main` function, why does it claim `Algo` needs to be specified when we call `length` as a method, but when we use UFCS (without specifying `Algo`) it seems to work fine?
2. Why does the UFCS usage in the second code block not work like the first?

[*playpen for code below*](https://play.rust-lang.org/?gist=767c3ed18a280fb246098dd1dc86d29a&version=stable&mode=debug)

```rust
pub struct Line<T> {
    start: (T, T),
    end: (T, T),
}

////////////

pub trait LengthAlgo<T> {
    fn length(line: Line<T>) -> T;
}

////////////

pub enum Haversine {}

impl<T> LengthAlgo<T> for Haversine {
    fn length(line: Line<T>) -> T {
        unimplemented!()
    }
}

pub enum Vincenty {}

impl<T> LengthAlgo<T> for Vincenty {
    fn length(line: Line<T>) -> T {
        unimplemented!()
    }
}

////////////

pub trait Length<T, Algo: LengthAlgo<T> = Haversine> {
    fn length(self) -> T;
}

impl<T, Algo: LengthAlgo<T>> Length<T, Algo> for Line<T> {
    fn length(self) -> T {
        Algo::length(self)
    }
}

////////////

fn main() {
    let line: Line<i32> = Line {
        start: (4, 6),
        end: (2, 23),
    };
    
    // This doesn't compile – error message says `Algo` type needs to be specified
    // let haversine_length = line.length();
    
    // This compiles, despite us not specifying the type for `Algo`
    let haversine_length = Length::<i32>::length(line);
}
```

[*playpen for code below*](https://play.rust-lang.org/?gist=d18f2bbaec2131b1fe8dd7b635807708&version=stable&mode=debug)

```rust
pub struct Line {
    start: (f32, f32),
    end: (f32, f32),
}

////////////

pub trait LengthAlgo {
    fn length(line: Line) -> f32;
}

////////////

pub enum Haversine {}

impl LengthAlgo for Haversine {
    fn length(line: Line) -> f32 {
        unimplemented!()
    }
}

pub enum Vincenty {}

impl LengthAlgo for Vincenty {
    fn length(line: Line) -> f32 {
        unimplemented!()
    }
}

////////////

pub trait Length<Algo: LengthAlgo = Haversine> {
    fn length(self) -> f32;
}

impl<Algo: LengthAlgo> Length<Algo> for Line {
    fn length(self) -> f32 {
        Algo::length(self)
    }
}

fn main() {
    let line: Line = Line {
        start: (4., 6.),
        end: (2., 23.),
    };
    
    // Neither line below compiles – error message says `Algo` type needs to be specified
    // let haversine_length = line.length();
    // let haversine_length = Length::length(line);
}
```