Skip to content
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

Tracking issue for future-incompatibility lint invalid_type_param_default #36887

Open
3 of 5 tasks
petrochenkov opened this issue Oct 1, 2016 · 38 comments
Open
3 of 5 tasks
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-future-incompatibility Category: Future-incompatibility lints C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@petrochenkov
Copy link
Contributor

petrochenkov commented Oct 1, 2016

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

@petrochenkov
Copy link
Contributor Author

@nikomatsakis, could you write a description for this?

@nikomatsakis
Copy link
Contributor

@petrochenkov done.

@nrc nrc added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Nov 17, 2016
@nrc
Copy link
Member

nrc commented Nov 28, 2016

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

@nikomatsakis
Copy link
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).

@RReverser
Copy link
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) { ... }.

@nikomatsakis
Copy link
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.

@RReverser
Copy link
Contributor

RReverser commented Apr 24, 2017

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?

bors added a commit that referenced this issue Jun 1, 2017
Turn sufficiently old compatibility lints into hard errors

It's been almost 7 months since #36894 was merged, so it's time to take the next step.

[breaking-change], needs crater run.

PRs/issues submitted to affected crates:
https://github.com/alexcrichton/ctest/pull/17
Sean1708/rusty-cheddar#55
m-r-r/helianto#3
azdle/virgil#1
rust-locale/rust-locale#24
mneumann/acyclic-network-rs#1
reem/rust-typemap#38

cc https://internals.rust-lang.org/t/moving-forward-on-forward-compatibility-lints/4204
cc #34537 #36887
Closes #36886
Closes #36888
Closes #36890
Closes #36891
Closes #36892
r? @nikomatsakis
frewsxcv added a commit to frewsxcv/rust that referenced this issue Jun 1, 2017
@randomPoison
Copy link
Contributor

I'm also curious as to what the issue is for default type arguments in generic functions. I'm running into a case where it would greatly help ergonomics of using a function with an optional generic parameter: https://is.gd/Gy9bXW

@Mark-Simulacrum Mark-Simulacrum added the C-future-incompatibility Category: Future-incompatibility lints label Jun 24, 2017
@Mark-Simulacrum Mark-Simulacrum added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC and removed C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC labels Jul 22, 2017
OverOrion added a commit to OverOrion/worker that referenced this issue Dec 1, 2022
…um`, `type`, or `trait` definitions

  --> cli/src/trusted_operation.rs:44:41
   |
44 | pub(crate) fn perform_trusted_operation<TG = TrustedGetter>(
   |                                         ^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #36887 <rust-lang/rust#36887>
   = note: `#[deny(invalid_type_param_default)]` on by default
@Starwort
Copy link

I'd also like this restriction to be lifted for functions, especially for trait functions. It would be much more ergonomic to have an API which allows default type parameters; For example, Iterator::collect could default to Vec<T>, while still allowing to be overridden by either type inference or an explicit turbofish; additionally Iterator::sum could be optimised for the common case where S = T (e.g. usize -> usize); other use-cases where an obvious default could be picked should be fairly common

@rambip
Copy link

rambip commented Sep 23, 2023

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

If I do:

fn foo<F: Fn() -> String=fn() -> String>(bar:Option<F>){}

fn main(){
    foo(Some(|| String::new()));
    foo(None)
}

Now it compiles !

@gsteinLTU
Copy link

For example, Iterator::collect could default to Vec<T>

I have to wonder how much time this would have saved people if it was like this from the start.

@rambip
Copy link

rambip commented Sep 27, 2023

And in essence, this is just a hint for the compiler saying "instead of raising type annotation needed for Foo, just try to replace with some concrete type to see if that works"
Maybe it is a completely different feature and a new issue should be open (default type parameters can create a bunch of strange situations), but it would be very cool to have this feature.

@QuineDot
Copy link

Default type parameters on functions are not completely ignored. Inference doesn't fallback to them just like default type parameters elsewhere, and there are less workarounds because you can't name the types of functions items.

But this works, for example:

#[allow(invalid_type_param_default)]
fn partial_default<T, U: Default = String>() -> U {
    U::default()
}

fn main() {
    let x = partial_default::<()>();
    println!("{}", std::any::type_name_of_val(&x));
}

Because if you have one or more non-defaulted parameters, you can omit defaulted parameters in a turbofish, and (unlike when all parameters are elided / when there is no turbofish), the elided parameters will take on their default values instead of being inference variables.

This is required for things like Vec<Element, Allocator> to work as intended with the default allocator, but happens to work for functions and probably other things, as well.

bors added a commit to rust-lang-ci/rust that referenced this issue Jul 12, 2024
… r=<try>

WIP: make invalid_type_param_default a hard error

Cc rust-lang#36887
`@rust-lang/types` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error. This should be cratered. (But I can also make it `FutureReleaseErrorReportInDeps` first if you prefer.)
@RalfJung
Copy link
Member

FWIW I did a crater run in #127655 and there's still quite a few crates affected by this lint -- mostly because of typemap.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 4, 2024
…t, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

`@rust-lang/types` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 4, 2024
…t, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

``@rust-lang/types`` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 4, 2024
…t, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

```@rust-lang/types``` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 5, 2024
…t, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

````@rust-lang/types```` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 5, 2024
…t, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

`````@rust-lang/types````` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Aug 5, 2024
Rollup merge of rust-lang#127655 - RalfJung:invalid_type_param_default, r=compiler-errors

turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`

`````@rust-lang/types````` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.

However, turns out that outright removing it right now would lead to [tons of crater regressions](rust-lang#127655 (comment)), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.

Fixes rust-lang#27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC rust-lang#36887
@tjpalmer
Copy link

tjpalmer commented Aug 9, 2024

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.

@EndilWayfare
Copy link

EndilWayfare commented Sep 7, 2024

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.

@RalfJung
Copy link
Member

RalfJung commented Sep 7, 2024 via email

@fmease fmease added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed B-unstable Blocker: Implemented in the nightly compiler and unstable. labels Sep 14, 2024
@fmease fmease changed the title Tracking issue for invalid_type_param_default compatibility lint Tracking issue for future-incompatibility lint invalid_type_param_default Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-future-incompatibility Category: Future-incompatibility lints C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
Archived in project