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`
This commit is contained in:
parent
337181e07d
commit
9b90e7e980
10 changed files with 139 additions and 4 deletions
|
@ -687,6 +687,9 @@ declare_features! (
|
||||||
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
|
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
|
||||||
(incomplete, trait_upcasting, "1.56.0", Some(65991), None),
|
(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),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -769,7 +769,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// (#83606): Do not emit a suggestion if the parent has an `impl Trait`
|
// (#83606): Do not emit a suggestion if the parent has an `impl Trait`
|
||||||
// as an argument otherwise it will cause the E0282 error.
|
// 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(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
"consider specifying the const argument",
|
"consider specifying the const argument",
|
||||||
|
|
|
@ -554,6 +554,7 @@ symbols! {
|
||||||
expected,
|
expected,
|
||||||
expf32,
|
expf32,
|
||||||
expf64,
|
expf64,
|
||||||
|
explicit_generic_args_with_impl_trait,
|
||||||
export_name,
|
export_name,
|
||||||
expr,
|
expr,
|
||||||
extended_key_value_attributes,
|
extended_key_value_attributes,
|
||||||
|
|
|
@ -459,7 +459,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
|
|
||||||
let default_counts = gen_params.own_defaults();
|
let default_counts = gen_params.own_defaults();
|
||||||
let param_counts = gen_params.own_counts();
|
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 {
|
||||||
|
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 =
|
let infer_lifetimes =
|
||||||
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
|
gen_pos != GenericArgPosition::Type && !gen_args.has_lifetime_params();
|
||||||
|
|
||||||
|
@ -588,6 +613,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
param_counts.consts + named_type_param_count
|
param_counts.consts + named_type_param_count
|
||||||
- default_counts.types
|
- default_counts.types
|
||||||
- default_counts.consts
|
- default_counts.consts
|
||||||
|
- synth_type_param_count
|
||||||
};
|
};
|
||||||
debug!("expected_min: {:?}", expected_min);
|
debug!("expected_min: {:?}", expected_min);
|
||||||
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
|
debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params());
|
||||||
|
@ -617,7 +643,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
seg: &hir::PathSegment<'_>,
|
seg: &hir::PathSegment<'_>,
|
||||||
generics: &ty::Generics,
|
generics: &ty::Generics,
|
||||||
) -> bool {
|
) -> 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| {
|
let impl_trait = generics.params.iter().any(|param| {
|
||||||
matches!(
|
matches!(
|
||||||
param.kind,
|
param.kind,
|
||||||
|
@ -630,7 +659,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
if explicit && impl_trait {
|
if impl_trait {
|
||||||
let spans = seg
|
let spans = seg
|
||||||
.args()
|
.args()
|
||||||
.args
|
.args
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
```
|
|
@ -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
|
||||||
|
}
|
|
@ -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`.
|
|
@ -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());
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue