Skip to content

Commit

Permalink
avoid creating an Instance only to immediately disassemble it again
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jul 13, 2024
1 parent 37ad6b2 commit 76237d4
Show file tree
Hide file tree
Showing 13 changed files with 54 additions and 114 deletions.
17 changes: 8 additions & 9 deletions compiler/rustc_error_codes/src/error_codes/E0158.md
Original file line number Diff line number Diff line change
@@ -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:

Expand All @@ -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 {
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand Down
33 changes: 2 additions & 31 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,37 +548,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
_ => 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 {
Expand Down
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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() {
}
Original file line number Diff line number Diff line change
@@ -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`.
5 changes: 3 additions & 2 deletions tests/ui/consts/issue-73976-polymorphic.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0158`.
3 changes: 2 additions & 1 deletion tests/ui/consts/issue-79137-toogeneric.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
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)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0158`.
5 changes: 3 additions & 2 deletions tests/ui/inline-const/const-match-pat-generic.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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) } => {},
| ^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0158`.
26 changes: 0 additions & 26 deletions tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs

This file was deleted.

15 changes: 0 additions & 15 deletions tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr

This file was deleted.

0 comments on commit 76237d4

Please sign in to comment.