diff options
| author | bors <bors@rust-lang.org> | 2025-01-24 11:12:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-01-24 11:12:01 +0000 |
| commit | 8231e8599e238ff4e717639bd68c6abb8579fe8d (patch) | |
| tree | bd5801d2bc7eb09acfa728ae6b5d83fafc249a1f /tests | |
| parent | 061ee95ce197dc9b276fc5363eddbfc0ecc08584 (diff) | |
| parent | c58fe21cb919aedce5408f478c86b19e8e17bab2 (diff) | |
| download | rust-8231e8599e238ff4e717639bd68c6abb8579fe8d.tar.gz rust-8231e8599e238ff4e717639bd68c6abb8579fe8d.zip | |
Auto merge of #135272 - BoxyUwU:generic_arg_infer_reliability_2, r=compiler-errors
Forbid usage of `hir` `Infer` const/ty variants in ambiguous contexts
The feature `generic_arg_infer` allows providing `_` as an argument to const generics in order to infer them. This introduces a syntactic ambiguity as to whether generic arguments are type or const arguments. In order to get around this we introduced a fourth `GenericArg` variant, `Infer` used to represent `_` as an argument to generic parameters when we don't know if its a type or a const argument.
This made hir visitors that care about `TyKind::Infer` or `ConstArgKind::Infer` very error prone as checking for `TyKind::Infer`s in `visit_ty` would find *some* type infer arguments but not *all* of them as they would sometimes be lowered to `GenericArg::Infer` instead.
Additionally the `visit_infer` method would previously only visit `GenericArg::Infer` not *all* infers (e.g. `TyKind::Infer`), this made it very easy to override `visit_infer` and expect it to visit all infers when in reality it would only visit *some* infers.
---
This PR aims to fix those issues by making the `TyKind` and `ConstArgKind` types generic over whether the infer types/consts are represented by `Ty/ConstArgKind::Infer` or out of line (e.g. by a `GenericArg::Infer` or accessible by overiding `visit_infer`). We then make HIR Visitors convert all const args and types to the versions where infer vars are stored out of line and call `visit_infer` in cases where a `Ty`/`Const` would previously have had a `Ty/ConstArgKind::Infer` variant:
API Summary
```rust
enum AmbigArg {}
enum Ty/ConstArgKind<Unambig = ()> {
...
Infer(Unambig),
}
impl Ty/ConstArg {
fn try_as_ambig_ty/ct(self) -> Option<Ty/ConstArg<AmbigArg>>;
}
impl Ty/ConstArg<AmbigArg> {
fn as_unambig_ty/ct(self) -> Ty/ConstArg;
}
enum InferKind {
Ty(Ty),
Const(ConstArg),
Ambig(InferArg),
}
trait Visitor {
...
fn visit_ty/const_arg(&mut self, Ty/ConstArg<AmbigArg>) -> Self::Result;
fn visit_infer(&mut self, id: HirId, sp: Span, kind: InferKind) -> Self::Result;
}
// blanket impl'd, not meant to be overriden
trait VisitorExt {
fn visit_ty/const_arg_unambig(&mut self, Ty/ConstArg) -> Self::Result;
}
fn walk_unambig_ty/const_arg(&mut V, Ty/ConstArg) -> Self::Result;
fn walk_ty/const_arg(&mut V, Ty/ConstArg<AmbigArg>) -> Self::Result;
```
The end result is that `visit_infer` visits *all* infer args and is also the *only* way to visit an infer arg, `visit_ty` and `visit_const_arg` can now no longer encounter a `Ty/ConstArgKind::Infer`. Representing this in the type system means that it is now very difficult to mess things up, either accessing `TyKind::Infer` "just works" and you won't miss *some* type infers- or it doesn't work and you have to look at `visit_infer` or some `GenericArg::Infer` which forces you to think about the full complexity involved.
Unfortunately there is no lint right now about explicitly matching on uninhabited variants, I can't find the context for why this is the case :woman_shrugging:
I'm not convinced the framing of un/ambig ty/consts is necessarily the right one but I'm not sure what would be better. I somewhat like calling them full/partial types based on the fact that `Ty<Partial>`/`Ty<Full>` directly specifies how many of the type kinds are actually represented compared to `Ty<Ambig>` which which leaves that to the reader to figure out based on the logical consequences of it the type being in an ambiguous position.
---
tool changes have been modified in their own commits for easier reviewing by anyone getting cc'd from subtree changes. I also attempted to split out "bug fixes arising from the refactoring" into their own commit so they arent lumped in with a big general refactor commit
Fixes #112110
Diffstat (limited to 'tests')
22 files changed, 98 insertions, 73 deletions
diff --git a/tests/ui/closures/binder/forbid_ambig_const_infers.rs b/tests/ui/closures/binder/forbid_ambig_const_infers.rs new file mode 100644 index 00000000000..e9d783711ee --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_const_infers.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +struct Foo<const N: usize>([u32; N]); + +fn main() { + let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&Foo([1_u32; 1])); +} diff --git a/tests/ui/closures/binder/forbid_ambig_const_infers.stderr b/tests/ui/closures/binder/forbid_ambig_const_infers.stderr new file mode 100644 index 00000000000..396c9e8c916 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_const_infers.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_ambig_const_infers.rs:6:33 + | +LL | let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/binder/forbid_ambig_type_infers.rs b/tests/ui/closures/binder/forbid_ambig_type_infers.rs new file mode 100644 index 00000000000..4e717ef3a17 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_type_infers.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +struct Foo<T>(T); + +fn main() { + let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0 }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&Foo(1_u32)); +} diff --git a/tests/ui/closures/binder/forbid_ambig_type_infers.stderr b/tests/ui/closures/binder/forbid_ambig_type_infers.stderr new file mode 100644 index 00000000000..8f19d710073 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_type_infers.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_ambig_type_infers.rs:6:33 + | +LL | let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0 }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/binder/forbid_const_infer.rs b/tests/ui/closures/binder/forbid_const_infer.rs new file mode 100644 index 00000000000..f5b8bf188df --- /dev/null +++ b/tests/ui/closures/binder/forbid_const_infer.rs @@ -0,0 +1,7 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +fn main() { + let c = for<'a> |b: &'a [u32; _]| -> u32 { b[0] }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&[1_u32; 2]); +} diff --git a/tests/ui/closures/binder/forbid_const_infer.stderr b/tests/ui/closures/binder/forbid_const_infer.stderr new file mode 100644 index 00000000000..e93685d400e --- /dev/null +++ b/tests/ui/closures/binder/forbid_const_infer.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_const_infer.rs:4:35 + | +LL | let c = for<'a> |b: &'a [u32; _]| -> u32 { b[0] }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs new file mode 100644 index 00000000000..81c42183b38 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ revisions: gate nogate +#![cfg_attr(gate, feature(generic_arg_infer))] + +fn main() { + // AST Types preserve parens for pretty printing reasons. This means + // that this is parsed as a `TyKind::Paren(TyKind::Infer)`. Generic + // arg lowering therefore needs to take into account not just `TyKind::Infer` + // but `TyKind::Infer` wrapped in arbitrarily many `TyKind::Paren`. + let a: Vec<(_)> = vec![1_u8]; + let a: Vec<(((((_)))))> = vec![1_u8]; +} diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index bd17d70a50b..1bb111b188d 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -18,19 +18,17 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error[E0747]: type provided when a constant was expected +error[E0658]: const arguments cannot yet be inferred with `_` --> $DIR/issue-62878.rs:10:11 | LL | foo::<_, { [1] }>(); | ^ | - = help: const arguments cannot yet be inferred with `_` -help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - | -LL + #![feature(generic_arg_infer)] - | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 3 previous errors -Some errors have detailed explanations: E0747, E0770. -For more information about an error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0658, E0770. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/issues/issue-62878.rs b/tests/ui/const-generics/issues/issue-62878.rs index 0b5269df85e..c80b46ddbc4 100644 --- a/tests/ui/const-generics/issues/issue-62878.rs +++ b/tests/ui/const-generics/issues/issue-62878.rs @@ -8,5 +8,5 @@ fn foo<const N: usize, const A: [u8; N]>() {} fn main() { foo::<_, { [1] }>(); - //[min]~^ ERROR: type provided when a constant was expected + //[min]~^ ERROR: const arguments cannot yet be inferred with `_` } diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 41039ae82a6..5fc2f7c1fe6 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -233,11 +233,6 @@ LL | fn foo<X: K<_, _>>(x: X) {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures - | -help: use type parameters instead - | -LL | fn foo<X: K<T, T>, T>(x: X) {} - | ~ ~ +++ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:54:34 diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr index 96fb4a53609..73e6988b09c 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr @@ -8,17 +8,15 @@ LL | let _y: [u8; _] = [0; 3]; = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0747]: type provided when a constant was expected +error[E0658]: const arguments cannot yet be inferred with `_` --> $DIR/feature-gate-generic_arg_infer.rs:18:20 | -LL | let _x = foo::<_>([1,2]); +LL | let _x = foo::<_>([1, 2]); | ^ | - = help: const arguments cannot yet be inferred with `_` -help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - | -LL + #![feature(generic_arg_infer)] - | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: using `_` for array lengths is unstable --> $DIR/feature-gate-generic_arg_infer.rs:11:27 @@ -32,5 +30,4 @@ LL | let _x: [u8; 3] = [0; _]; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0747. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs index de4b7078ea6..147978b0557 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs @@ -4,7 +4,7 @@ #![cfg_attr(feature, feature(generic_arg_infer))] fn foo<const N: usize>(_: [u8; N]) -> [u8; N] { - [0; N] + [0; N] } fn bar() { @@ -15,7 +15,7 @@ fn bar() { } fn main() { - let _x = foo::<_>([1,2]); - //[normal]~^ ERROR: type provided when a constant was expected + let _x = foo::<_>([1, 2]); + //[normal]~^ ERROR: const arguments cannot yet be inferred with `_` bar(); } diff --git a/tests/ui/generics/issue-79605.stderr b/tests/ui/generics/issue-79605.stderr index 67fed200f96..049f77a6584 100644 --- a/tests/ui/generics/issue-79605.stderr +++ b/tests/ui/generics/issue-79605.stderr @@ -3,11 +3,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures | LL | impl X<'_, _> {} | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | impl<T> X<'_, T> {} - | +++ ~ error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-span-issue-116502.stderr b/tests/ui/macros/macro-span-issue-116502.stderr index da02855660a..2a581f7031b 100644 --- a/tests/ui/macros/macro-span-issue-116502.stderr +++ b/tests/ui/macros/macro-span-issue-116502.stderr @@ -17,13 +17,6 @@ LL | T: Trait<m!()>; | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use type parameters instead - | -LL ~ U -LL | }; -LL | } -LL ~ struct S<U>(m!(), T) - | error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-14303-fncall.full.stderr b/tests/ui/parser/issues/issue-14303-fncall.full.stderr index 1986f70bf67..5a017c85c16 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.full.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.full.stderr @@ -1,8 +1,8 @@ -error[E0747]: type provided when a lifetime was expected - --> $DIR/issue-14303-fncall.rs:15:26 +error[E0747]: placeholder provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:12:77 | -LL | .collect::<Vec<S<_, 'a>>>(); - | ^ +LL | let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr index 2de59b8c746..5a017c85c16 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr @@ -1,8 +1,8 @@ -error[E0747]: inferred provided when a lifetime was expected - --> $DIR/issue-14303-fncall.rs:15:26 +error[E0747]: placeholder provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:12:77 | -LL | .collect::<Vec<S<_, 'a>>>(); - | ^ +LL | let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-14303-fncall.rs b/tests/ui/parser/issues/issue-14303-fncall.rs index 59d4eab06d6..8f7fbec9470 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.rs +++ b/tests/ui/parser/issues/issue-14303-fncall.rs @@ -3,18 +3,15 @@ // we need the above to avoid ast borrowck failure in recovered code #![cfg_attr(generic_arg, feature(generic_arg_infer))] - struct S<'a, T> { a: &'a T, b: &'a T, } fn foo<'a, 'b>(start: &'a usize, end: &'a usize) { - let _x = (*start..*end) - .map(|x| S { a: start, b: end }) - .collect::<Vec<S<_, 'a>>>(); - //[generic_arg]~^ ERROR inferred provided when a lifetime was expected - //[full]~^^ ERROR type provided when a lifetime was expected + let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + //[generic_arg]~^ ERROR placeholder provided when a lifetime was expected + //[full]~^^ ERROR placeholder provided when a lifetime was expected } fn main() {} diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr index a4b65256574..6559845c23e 100644 --- a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr +++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -17,10 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | -help: consider specifying the generic argument - | -LL | .sum::<S>() - | ~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index 85a943c26e2..16bbc996d90 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -28,10 +28,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-77179.rs:18:25 | LL | fn bar() -> Pointer<_>; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error: aborting due to 3 previous errors diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 55f45ade388..c5f8b2764ec 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -4,7 +4,7 @@ type Pat<const START: u32, const END: u32> = std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); //~^ ERROR type and const arguments are not allowed on const parameter `START` -//~| ERROR type arguments are not allowed on const parameter `END` +//~| ERROR generic arguments are not allowed on const parameter `END` //~| ERROR associated item constraints are not allowed here fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index 7f4e6e314f5..f31809bf397 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -12,11 +12,11 @@ note: const parameter `START` defined here LL | type Pat<const START: u32, const END: u32> = | ^^^^^ -error[E0109]: type arguments are not allowed on const parameter `END` +error[E0109]: generic arguments are not allowed on const parameter `END` --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 | LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | --- ^ type argument not allowed + | --- ^ generic argument not allowed | | | not allowed on const parameter `END` | diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index c97b9312076..d2a850d7dbf 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -507,22 +507,12 @@ LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures - | -help: use type parameters instead - | -LL | impl<T> BadTrait<T> for BadStruct<T> {} - | +++ ~ ~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn impl_trait<T>() -> impl BadTrait<T> { - | +++ ~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:167:25 |
