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

Implement a explicit_generic_args_with_impl_trait feature gate #86176

Merged
merged 1 commit into from
Aug 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,9 @@ declare_features! (
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
(incomplete, trait_upcasting, "1.56.0", Some(65991), None),

/// Allows explicit generic arguments specification with `impl Trait` present.
(active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we can just co-opt that issue to be a tracking issue, yeah.


// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

// (#83606): Do not emit a suggestion if the parent has an `impl Trait`
// as an argument otherwise it will cause the E0282 error.
if !has_impl_trait {
if !has_impl_trait || self.tcx.features().explicit_generic_args_with_impl_trait {
err.span_suggestion_verbose(
span,
"consider specifying the const argument",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ symbols! {
expected,
expf32,
expf64,
explicit_generic_args_with_impl_trait,
export_name,
expr,
extended_key_value_attributes,
Expand Down
35 changes: 32 additions & 3 deletions compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {

let default_counts = gen_params.own_defaults();
let param_counts = gen_params.own_counts();
let named_type_param_count = param_counts.types - has_self as usize;

// Subtracting from param count to ensure type params synthesized from `impl Trait`
// cannot be explictly specified even with `explicit_generic_args_with_impl_trait`
// feature enabled.
let synth_type_param_count = if tcx.features().explicit_generic_args_with_impl_trait {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like a small comment here just explaining what we're doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

gen_params
.params
.iter()
.filter(|param| {
matches!(
param.kind,
ty::GenericParamDefKind::Type {
synthetic: Some(
hir::SyntheticTyParamKind::ImplTrait
| hir::SyntheticTyParamKind::FromAttr
),
..
}
)
})
.count()
} else {
0
};
let named_type_param_count =
param_counts.types - has_self as usize - synth_type_param_count;
let infer_lifetimes =
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();

Expand Down Expand Up @@ -588,6 +613,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
param_counts.consts + named_type_param_count
- default_counts.types
- default_counts.consts
- synth_type_param_count
};
debug!("expected_min: {:?}", expected_min);
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
Expand Down Expand Up @@ -617,7 +643,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
seg: &hir::PathSegment<'_>,
generics: &ty::Generics,
) -> bool {
let explicit = !seg.infer_args;
if seg.infer_args || tcx.features().explicit_generic_args_with_impl_trait {
return false;
}

let impl_trait = generics.params.iter().any(|param| {
matches!(
param.kind,
Expand All @@ -630,7 +659,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
});

if explicit && impl_trait {
if impl_trait {
let spans = seg
.args()
.args
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# `explicit_generic_args_with_impl_trait`

The tracking issue for this feature is: [#83701]

[#83701]: https://github.com/rust-lang/rust/issues/83701

------------------------

The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even
when `impl Trait` is used in argument position.

A simple example is:

```rust
#![feature(explicit_generic_args_with_impl_trait)]

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}

fn main() {
foo::<str>("".to_string());
}
```

This is currently rejected:

```text
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> src/main.rs:6:11
|
6 | foo::<str>("".to_string());
| ^^^ explicit generic argument not allowed

```

However it would compile if `explicit_generic_args_with_impl_trait` is enabled.

Note that the synthetic type parameters from `impl Trait` are still implicit and you
cannot explicitly specify these:

```rust,compile_fail
#![feature(explicit_generic_args_with_impl_trait)]

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn bar<T: ?Sized, F: AsRef<T>>(_f: F) {}

fn main() {
bar::<str, _>("".to_string()); // Okay
bar::<str, String>("".to_string()); // Okay

foo::<str>("".to_string()); // Okay
foo::<str, String>("".to_string()); // Error, you cannot specify `impl Trait` explicitly
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#![feature(explicit_generic_args_with_impl_trait)]

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}

fn main() {
foo::<str, String>("".to_string()); //~ ERROR E0107
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0107]: this function takes at most 1 generic argument but 2 generic arguments were supplied
--> $DIR/explicit-generic-args-for-impl.rs:6:5
|
LL | foo::<str, String>("".to_string());
| ^^^ ------ help: remove this generic argument
| |
| expected at most 1 generic argument
|
note: function defined here, with at most 1 generic parameter: `T`
--> $DIR/explicit-generic-args-for-impl.rs:3:4
|
LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
| ^^^ -

error: aborting due to previous error

For more information about this error, try `rustc --explain E0107`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// check-pass

#![feature(explicit_generic_args_with_impl_trait)]

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}

fn main() {
foo::<str>("".to_string());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// gate-test-explicit_generic_args_with_impl_trait

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}

fn main() {
foo::<str>("".to_string()); //~ ERROR E0632
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
--> $DIR/feature-gate.rs:6:11
|
LL | foo::<str>("".to_string());
| ^^^ explicit generic argument not allowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0632`.