avoid creating an Instance only to immediately disassemble it again
This commit is contained in:
parent
86ce911f90
commit
67c99d6338
@ -1,5 +1,4 @@
|
||||
An associated `const`, `const` parameter or `static` has been referenced
|
||||
in a pattern.
|
||||
A generic parameter or `static` has been referenced in a pattern.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
@ -15,25 +14,25 @@ trait Bar {
|
||||
|
||||
fn test<A: Bar>(arg: Foo) {
|
||||
match arg {
|
||||
A::X => println!("A::X"), // error: E0158: associated consts cannot be
|
||||
// referenced in patterns
|
||||
A::X => println!("A::X"), // error: E0158: constant pattern depends
|
||||
// on a generic parameter
|
||||
Foo::Two => println!("Two")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Associated `const`s cannot be referenced in patterns because it is impossible
|
||||
Generic parameters cannot be referenced in patterns because it is impossible
|
||||
for the compiler to prove exhaustiveness (that some pattern will always match).
|
||||
Take the above example, because Rust does type checking in the *generic*
|
||||
method, not the *monomorphized* specific instance. So because `Bar` could have
|
||||
theoretically infinite implementations, there's no way to always be sure that
|
||||
theoretically arbitrary implementations, there's no way to always be sure that
|
||||
`A::X` is `Foo::One`. So this code must be rejected. Even if code can be
|
||||
proven exhaustive by a programmer, the compiler cannot currently prove this.
|
||||
|
||||
The same holds true of `const` parameters and `static`s.
|
||||
The same holds true of `static`s.
|
||||
|
||||
If you want to match against an associated `const`, `const` parameter or
|
||||
`static` consider using a guard instead:
|
||||
If you want to match against a `const` that depends on a generic parameter or a
|
||||
`static`, consider using a guard instead:
|
||||
|
||||
```
|
||||
trait Trait {
|
||||
|
@ -4,8 +4,6 @@ mir_build_already_borrowed = cannot borrow value as mutable because it is also b
|
||||
|
||||
mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
|
||||
|
||||
mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
|
||||
|
||||
mir_build_bindings_with_variant_name =
|
||||
pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
|
||||
.suggestion = to match on the variant, qualify the path
|
||||
|
@ -566,13 +566,6 @@ pub(crate) struct StaticInPattern {
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_assoc_const_in_pattern, code = E0158)]
|
||||
pub(crate) struct AssocConstInPattern {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_const_param_in_pattern, code = E0158)]
|
||||
pub(crate) struct ConstParamInPattern {
|
||||
@ -597,7 +590,7 @@ pub(crate) struct UnreachablePattern {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_const_pattern_depends_on_generic_parameter)]
|
||||
#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
|
||||
pub(crate) struct ConstPatternDependsOnGenericParameter {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
|
@ -548,37 +548,8 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
|
||||
_ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])),
|
||||
};
|
||||
|
||||
// Use `Reveal::All` here because patterns are always monomorphic even if their function
|
||||
// isn't.
|
||||
let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
|
||||
// N.B. There is no guarantee that args collected in typeck results are fully normalized,
|
||||
// so they need to be normalized in order to pass to `Instance::resolve`, which will ICE
|
||||
// if given unnormalized types.
|
||||
let args = self
|
||||
.tcx
|
||||
.normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_args(id));
|
||||
let instance = match ty::Instance::try_resolve(self.tcx, param_env_reveal_all, def_id, args)
|
||||
{
|
||||
Ok(Some(i)) => i,
|
||||
Ok(None) => {
|
||||
// It should be assoc consts if there's no error but we cannot resolve it.
|
||||
debug_assert!(is_associated_const);
|
||||
|
||||
let e = self.tcx.dcx().emit_err(AssocConstInPattern { span });
|
||||
return pat_from_kind(PatKind::Error(e));
|
||||
}
|
||||
|
||||
Err(_) => {
|
||||
let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span });
|
||||
return pat_from_kind(PatKind::Error(e));
|
||||
}
|
||||
};
|
||||
|
||||
let c = ty::Const::new_unevaluated(
|
||||
self.tcx,
|
||||
ty::UnevaluatedConst { def: instance.def_id(), args: instance.args },
|
||||
);
|
||||
|
||||
let args = self.typeck_results.node_args(id);
|
||||
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
|
||||
let pattern = self.const_to_pat(c, ty, id, span);
|
||||
|
||||
if !is_associated_const {
|
||||
|
@ -3449,7 +3449,6 @@ ui/pattern/issue-6449.rs
|
||||
ui/pattern/issue-66270-pat-struct-parser-recovery.rs
|
||||
ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs
|
||||
ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs
|
||||
ui/pattern/issue-68393-let-pat-assoc-constant.rs
|
||||
ui/pattern/issue-72565.rs
|
||||
ui/pattern/issue-72574-1.rs
|
||||
ui/pattern/issue-72574-2.rs
|
||||
|
@ -1,15 +0,0 @@
|
||||
error[E0158]: associated consts cannot be referenced in patterns
|
||||
--> $DIR/associated-const-type-parameter-arms.rs:20:9
|
||||
|
|
||||
LL | A::X => println!("A::X"),
|
||||
| ^^^^
|
||||
|
||||
error[E0158]: associated consts cannot be referenced in patterns
|
||||
--> $DIR/associated-const-type-parameter-arms.rs:22:9
|
||||
|
|
||||
LL | B::X => println!("B::X"),
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
@ -18,12 +18,18 @@ impl Foo for Def {
|
||||
pub fn test<A: Foo, B: Foo>(arg: EFoo) {
|
||||
match arg {
|
||||
A::X => println!("A::X"),
|
||||
//~^ error: associated consts cannot be referenced in patterns [E0158]
|
||||
//~^ error: constant pattern depends on a generic parameter
|
||||
B::X => println!("B::X"),
|
||||
//~^ error: associated consts cannot be referenced in patterns [E0158]
|
||||
//~^ error: constant pattern depends on a generic parameter
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
//~^ ERROR constant pattern depends on a generic parameter
|
||||
let A::X = arg;
|
||||
//~^ ERROR constant pattern depends on a generic parameter
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:20:9
|
||||
|
|
||||
LL | A::X => println!("A::X"),
|
||||
| ^^^^
|
||||
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:22:9
|
||||
|
|
||||
LL | B::X => println!("B::X"),
|
||||
| ^^^^
|
||||
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:30:9
|
||||
|
|
||||
LL | let A::X = arg;
|
||||
| ^^^^
|
||||
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:28:48
|
||||
|
|
||||
LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
@ -1,10 +1,10 @@
|
||||
error: constant pattern depends on a generic parameter
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/issue-73976-polymorphic.rs:20:37
|
||||
|
|
||||
LL | matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: constant pattern depends on a generic parameter
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/issue-73976-polymorphic.rs:31:42
|
||||
|
|
||||
LL | matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
|
||||
@ -12,3 +12,4 @@ LL | matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: constant pattern depends on a generic parameter
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/issue-79137-toogeneric.rs:12:43
|
||||
|
|
||||
LL | matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
|
||||
@ -6,3 +6,4 @@ LL | matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: constant pattern depends on a generic parameter
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:7:9
|
||||
|
|
||||
LL | const { V } => {},
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: constant pattern depends on a generic parameter
|
||||
error[E0158]: constant pattern depends on a generic parameter
|
||||
--> $DIR/const-match-pat-generic.rs:19:9
|
||||
|
|
||||
LL | const { f(V) } => {},
|
||||
@ -12,3 +12,4 @@ LL | const { f(V) } => {},
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
@ -1,26 +0,0 @@
|
||||
pub enum EFoo {
|
||||
A,
|
||||
}
|
||||
|
||||
pub trait Foo {
|
||||
const X: EFoo;
|
||||
}
|
||||
|
||||
struct Abc;
|
||||
|
||||
impl Foo for Abc {
|
||||
const X: EFoo = EFoo::A;
|
||||
}
|
||||
|
||||
struct Def;
|
||||
impl Foo for Def {
|
||||
const X: EFoo = EFoo::A;
|
||||
}
|
||||
|
||||
pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
//~^ ERROR associated consts cannot be referenced in patterns
|
||||
let A::X = arg;
|
||||
//~^ ERROR associated consts cannot be referenced in patterns
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,15 +0,0 @@
|
||||
error[E0158]: associated consts cannot be referenced in patterns
|
||||
--> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9
|
||||
|
|
||||
LL | let A::X = arg;
|
||||
| ^^^^
|
||||
|
||||
error[E0158]: associated consts cannot be referenced in patterns
|
||||
--> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40
|
||||
|
|
||||
LL | pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
Loading…
Reference in New Issue
Block a user