Skip to content

Commit 9b90e7e

Browse files
committed
Implement a explicit_generic_args_with_impl_trait feature gate
When this gate is enabled, explicit generic arguments can be specified even if `impl Trait` is used in argument position. Generic arguments can only be specified for explicit generic parameters but not for the synthetic type parameters from `impl Trait`
1 parent 337181e commit 9b90e7e

File tree

10 files changed

+139
-4
lines changed

10 files changed

+139
-4
lines changed

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,9 @@ declare_features! (
687687
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
688688
(incomplete, trait_upcasting, "1.56.0", Some(65991), None),
689689

690+
/// Allows explicit generic arguments specification with `impl Trait` present.
691+
(active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None),
692+
690693
// -------------------------------------------------------------------------
691694
// feature-group-end: actual feature gates
692695
// -------------------------------------------------------------------------

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
769769

770770
// (#83606): Do not emit a suggestion if the parent has an `impl Trait`
771771
// as an argument otherwise it will cause the E0282 error.
772-
if !has_impl_trait {
772+
if !has_impl_trait || self.tcx.features().explicit_generic_args_with_impl_trait {
773773
err.span_suggestion_verbose(
774774
span,
775775
"consider specifying the const argument",

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ symbols! {
554554
expected,
555555
expf32,
556556
expf64,
557+
explicit_generic_args_with_impl_trait,
557558
export_name,
558559
expr,
559560
extended_key_value_attributes,

compiler/rustc_typeck/src/astconv/generics.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
459459

460460
let default_counts = gen_params.own_defaults();
461461
let param_counts = gen_params.own_counts();
462-
let named_type_param_count = param_counts.types - has_self as usize;
462+
463+
// Subtracting from param count to ensure type params synthesized from `impl Trait`
464+
// cannot be explictly specified even with `explicit_generic_args_with_impl_trait`
465+
// feature enabled.
466+
let synth_type_param_count = if tcx.features().explicit_generic_args_with_impl_trait {
467+
gen_params
468+
.params
469+
.iter()
470+
.filter(|param| {
471+
matches!(
472+
param.kind,
473+
ty::GenericParamDefKind::Type {
474+
synthetic: Some(
475+
hir::SyntheticTyParamKind::ImplTrait
476+
| hir::SyntheticTyParamKind::FromAttr
477+
),
478+
..
479+
}
480+
)
481+
})
482+
.count()
483+
} else {
484+
0
485+
};
486+
let named_type_param_count =
487+
param_counts.types - has_self as usize - synth_type_param_count;
463488
let infer_lifetimes =
464489
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
465490

@@ -588,6 +613,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
588613
param_counts.consts + named_type_param_count
589614
- default_counts.types
590615
- default_counts.consts
616+
- synth_type_param_count
591617
};
592618
debug!("expected_min: {:?}", expected_min);
593619
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
@@ -617,7 +643,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
617643
seg: &hir::PathSegment<'_>,
618644
generics: &ty::Generics,
619645
) -> bool {
620-
let explicit = !seg.infer_args;
646+
if seg.infer_args || tcx.features().explicit_generic_args_with_impl_trait {
647+
return false;
648+
}
649+
621650
let impl_trait = generics.params.iter().any(|param| {
622651
matches!(
623652
param.kind,
@@ -630,7 +659,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
630659
)
631660
});
632661

633-
if explicit && impl_trait {
662+
if impl_trait {
634663
let spans = seg
635664
.args()
636665
.args
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# `explicit_generic_args_with_impl_trait`
2+
3+
The tracking issue for this feature is: [#83701]
4+
5+
[#83701]: https://github.com/rust-lang/rust/issues/83701
6+
7+
------------------------
8+
9+
The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even
10+
when `impl Trait` is used in argument position.
11+
12+
A simple example is:
13+
14+
```rust
15+
#![feature(explicit_generic_args_with_impl_trait)]
16+
17+
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
18+
19+
fn main() {
20+
foo::<str>("".to_string());
21+
}
22+
```
23+
24+
This is currently rejected:
25+
26+
```text
27+
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
28+
--> src/main.rs:6:11
29+
|
30+
6 | foo::<str>("".to_string());
31+
| ^^^ explicit generic argument not allowed
32+
33+
```
34+
35+
However it would compile if `explicit_generic_args_with_impl_trait` is enabled.
36+
37+
Note that the synthetic type parameters from `impl Trait` are still implicit and you
38+
cannot explicitly specify these:
39+
40+
```rust,compile_fail
41+
#![feature(explicit_generic_args_with_impl_trait)]
42+
43+
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
44+
fn bar<T: ?Sized, F: AsRef<T>>(_f: F) {}
45+
46+
fn main() {
47+
bar::<str, _>("".to_string()); // Okay
48+
bar::<str, String>("".to_string()); // Okay
49+
50+
foo::<str>("".to_string()); // Okay
51+
foo::<str, String>("".to_string()); // Error, you cannot specify `impl Trait` explicitly
52+
}
53+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(explicit_generic_args_with_impl_trait)]
2+
3+
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
4+
5+
fn main() {
6+
foo::<str, String>("".to_string()); //~ ERROR E0107
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0107]: this function takes at most 1 generic argument but 2 generic arguments were supplied
2+
--> $DIR/explicit-generic-args-for-impl.rs:6:5
3+
|
4+
LL | foo::<str, String>("".to_string());
5+
| ^^^ ------ help: remove this generic argument
6+
| |
7+
| expected at most 1 generic argument
8+
|
9+
note: function defined here, with at most 1 generic parameter: `T`
10+
--> $DIR/explicit-generic-args-for-impl.rs:3:4
11+
|
12+
LL | fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
13+
| ^^^ -
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0107`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
3+
#![feature(explicit_generic_args_with_impl_trait)]
4+
5+
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
6+
7+
fn main() {
8+
foo::<str>("".to_string());
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// gate-test-explicit_generic_args_with_impl_trait
2+
3+
fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
4+
5+
fn main() {
6+
foo::<str>("".to_string()); //~ ERROR E0632
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
2+
--> $DIR/feature-gate.rs:6:11
3+
|
4+
LL | foo::<str>("".to_string());
5+
| ^^^ explicit generic argument not allowed
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0632`.

0 commit comments

Comments
 (0)