Skip to content

Tracking issue for future-incompatibility lint invalid_type_param_default #36887

Open

Description

@petrochenkov

View all comments

This is the summary issue for the invalid_type_param_default
future-compatibility warning and other related errors. The goal of
this page is describe why this change was made and how you can fix
code that is affected by it. It also provides a place to ask questions
or register a complaint if you feel the change should not be made. For
more information on the policy around future-compatibility warnings,
see our breaking change policy guidelines.

What is the warning for?

Type parameter defaults outside of type declarations were never intended
to be permitted, but some early versions of Rust did accept them. For
example:

struct Foo<T=i32> { 
    // the default of `i32` is legal here, since this
    // is a type declaration
}

impl<T=i32> Debug for Foo<T> { .. }
//   ^^^^^ default not legal here, in an impl

fn bar<T=i32>(x: T) { }
//     ^^^^^ default not legal here, in a fn

When will this warning become a hard error?

At the beginning of each 6-week release cycle, the Rust compiler team
will review the set of outstanding future compatibility warnings and
nominate some of them for Final Comment Period. Toward the end of
the cycle, we will review any comments and make a final determination
whether to convert the warning into a hard error or remove it
entirely.

Current status

Activity

  1. petrochenkov commented on Oct 1, 2016

    @petrochenkov
    ContributorAuthor

    @nikomatsakis, could you write a description for this?

  2. added
    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.
    on Oct 7, 2016
  3. nikomatsakis commented on Oct 11, 2016

    @nikomatsakis
    Contributor
  4. added
    T-langRelevant to the language team
    and removed
    T-langRelevant to the language team
    on Nov 17, 2016
  5. nrc commented on Nov 28, 2016

    @nrc
    Member

    Where can I find discussion of this issue? I don't see any on RFC 213, nor its tracking issue (#27336).

  6. nikomatsakis commented on Nov 28, 2016

    @nikomatsakis
    Contributor

    @nrc perhaps I should have phrased the summary with slightly differently. I think the main thing is that defaults were being accepted in stable code but ignored, unless you opt in to a feature gate, which gives them some semantics (but semantics that I now think I disagree with).

  7. added
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    on Mar 1, 2017
  8. RReverser commented on Apr 23, 2017

    @RReverser
    Contributor

    Is there a reason this is being phased out on functions?

    It's sometimes useful to have fn do_smth<A, B=A>(a: A, b: B) { ... }.

  9. nikomatsakis commented on Apr 24, 2017

    @nikomatsakis
    Contributor

    @RReverser Yes. Because, IIRC, they are basically ignored on stable Rust. On nightly Rust, meanwhile, we were considering various possible meanings, but have not yet found one that we are satisfied with.

  10. RReverser commented on Apr 24, 2017

    @RReverser
    Contributor

    Ok, I'm now curious... where can I read about other possible meanings? The expectation seems pretty straightforward, just like in case with struct - that with fn do_smth<T=SomeType>() {}, do_smth() would be equivalent do do_smth::<SomeType>() but maybe I'm missing some issues?

  11. added a commit that references this issue on Jun 1, 2017
  12. 42 remaining items

  13. added 2 commits that reference this issue on Aug 5, 2024
  14. added a commit that references this issue on Aug 5, 2024
  15. tjpalmer commented on Aug 9, 2024

    @tjpalmer

    It is especially usefull for optional functions:

    fn foo<F: Fn() -> String>(bar:Option<F>){}
    
    fn main(){
        foo(Some(|| String::new()));
        foo(None)
    }

    Here, I have to use turbofish syntax even if it is irrelevant

    Similar problem for things like Option<impl ToString>. Having to say something like None::<String> is sort of silly.

  16. EndilWayfare commented on Sep 7, 2024

    @EndilWayfare

    euclid is another example of a class of use-case in which this is useful for ergonomic/noise-reduction reasons.

    The geometric primitives from this crate have an "optional" type parameter to specify unit of measure, but it's not really optional. You don't have to make active use of it, but you do have to mention it in your client code regardless.

    use euclid::UnknownUnit;
    // Equivalent to 
    // `type Point2D<T> = euclid::Point<T, UnknownUnit>;`
    use euclid::default::Point2D;
    
    pub fn my_silly_point<U>() -> euclid::Point2D<i32, U> {
        Point2D::new(42, 21)
    }
    
    pub fn also_my_silly_point() -> Point2D<i32> {
        my_silly_point()
    }
    
    fn no_units_pls() {
        let leaky_implementation_details = my_silly_point::<UnknownUnit>();
        let strange_and_awkward = my_silly_point::<()>();
    
        let but_i_can = also_my_silly_point();
    }
    
    fn im_already_using_units() {
        struct ScreenSpace;
    
        let center = euclid::Point2D::<i32, ScreenSpace>::new(2560, 1440) / 2;
    
        let i_can = center - my_silly_point();
    
        let but_i_have_to = center - also_my_silly_point().cast_unit();
        let or_maybe_for_some_reason = center - euclid::Point2D::from_untyped(also_my_silly_point());
    }

    I don't know why euclid chooses to uses a type alias instead of a default type parameter, or even if this is even a deliberate design decision. But, if a crate author decides they don't like default type parameters and you do like default type parameters, functions-with-default-type-parameters would let you have/emulate them without, e.g., a redundant wrapper struct.

  17. RalfJung commented on Sep 7, 2024

    @RalfJung
    Member
  18. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    on Sep 14, 2024
  19. changed the title [-]Tracking issue for `invalid_type_param_default` compatibility lint[/-] [+]Tracking issue for future-incompatibility lint `invalid_type_param_default`[/+] on Sep 14, 2024
  20. Houtamelo commented on May 1, 2025

    @Houtamelo
    Contributor

    Based on the comments it is very clear that allow default type parameters in function signatures is desirable. Is there an RFC for this already? If not, I could open it.

  21. fmease commented on May 1, 2025

    @fmease
    Member

    I strongly recommend to read the following first: https://internals.rust-lang.org/t/interaction-of-user-defined-and-integral-fallbacks-with-inference/2496/2 (linked from #2733).

    Also CC #98931 (comment):

    In expression position, a lack of generic arguments leads to the compiler supplying inference variables for all generic parameters (I'm ignoring lifetime elision here). These inference variables don't know a lot about their origin starting out, most notably the fact that there could be "defaults" for them. They are disconnected from that notion, so naturally there's no way for the type checker to consider the defaults.

    And while we could almost trivially equip their origin (e.g. TypeVariableOrigin in the compiler) with a notion of defaults, the problem lies in the question of when exactly to apply said default during the inference process. This is why there has been no progress whatsoever on this feature.

  22. added
    T-typesRelevant to the types team, which will review and decide on the PR/issue.
    on Jun 6, 2025
  23. valarauca commented on Apr 2, 2026

    @valarauca

    So 10 years later, is this actually happening or not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-future-incompatibilityCategory: Future-incompatibility lintsC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions