Skip to content

Commit

Permalink
Rollup merge of rust-lang#86176 - nbdd0121:explicit-generic-args, r=j…
Browse files Browse the repository at this point in the history
…ackh726

Implement a `explicit_generic_args_with_impl_trait` feature gate

Implements rust-lang#83701

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`

So code like this will be accepted:
```rust
#![feature(explicit_generic_args_with_impl_trait)]

fn foo<T: ?Sized>(_f: impl AsRef<T>) {}
fn main() {
    foo::<str>("".to_string());
}
```
  • Loading branch information
camsteffen authored Aug 2, 2021
2 parents d08460e + 9b90e7e commit 14f3418
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 4 deletions.
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),

// -------------------------------------------------------------------------
// 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 {
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`.

0 comments on commit 14f3418

Please sign in to comment.