Skip to content

Commit 7314f82

Browse files
committed
Better recover static/const type in type_of
When the type is an inferred placeholder or an error, we used to infer the type for an error message and then return `TyKind::Error`. Now we return the proper type, which helps follow-up code do more checking. The primary motivation for this was fixing the const-eval mutability assertion bug, because this commit forwards the inferred type to that assertion, but it is also just nicer in general.
1 parent b81adab commit 7314f82

File tree

9 files changed

+88
-15
lines changed

9 files changed

+88
-15
lines changed

compiler/rustc_hir_analysis/src/collect/type_of.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -571,8 +571,7 @@ fn infer_placeholder_type<'a>(
571571
// then the user may have written e.g. `const A = 42;`.
572572
// In this case, the parser has stashed a diagnostic for
573573
// us to improve in typeck so we do that now.
574-
let guar = tcx
575-
.dcx()
574+
tcx.dcx()
576575
.try_steal_modify_and_emit_err(span, StashKey::ItemNoType, |err| {
577576
if !ty.references_error() {
578577
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic).
@@ -619,7 +618,16 @@ fn infer_placeholder_type<'a>(
619618
}
620619
diag.emit()
621620
});
622-
Ty::new_error(tcx, guar)
621+
622+
// Typeck returns regions as erased. We can't deal with erased regions here though, so we
623+
// turn them into `&'static`, which is *generally* correct for statics and consts.
624+
// Assoc consts can reference generic lifetimes from the parent generics, but treating them
625+
// as static is unlikely to cause issues.
626+
let ty = tcx.fold_regions(ty, |region, _| match region.kind() {
627+
ty::ReErased => tcx.lifetimes.re_static,
628+
_ => region,
629+
});
630+
ty
623631
}
624632

625633
fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {

tests/crashes/124164.rs

-4
This file was deleted.

tests/ui/generic-const-items/assoc-const-missing-type.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ impl Trait for () {
1313
//~^ ERROR missing type for `const` item
1414
//~| ERROR mismatched types
1515
//~| ERROR mismatched types
16+
//~| ERROR implemented const `K` has an incompatible type for trait
1617
const Q = "";
1718
//~^ ERROR missing type for `const` item
1819
//~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration

tests/ui/generic-const-items/assoc-const-missing-type.stderr

+20-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,24 @@ error: missing type for `const` item
1515
LL | const K<T> = ();
1616
| ^ help: provide a type for the associated constant: `()`
1717

18+
error[E0326]: implemented const `K` has an incompatible type for trait
19+
--> $DIR/assoc-const-missing-type.rs:12:15
20+
|
21+
LL | const K<T> = ();
22+
| - ^ expected type parameter `T`, found `()`
23+
| |
24+
| expected this type parameter
25+
|
26+
note: type in trait
27+
--> $DIR/assoc-const-missing-type.rs:7:17
28+
|
29+
LL | const K<T>: T;
30+
| ^
31+
= note: expected type parameter `T`
32+
found unit type `()`
33+
1834
error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration
19-
--> $DIR/assoc-const-missing-type.rs:16:12
35+
--> $DIR/assoc-const-missing-type.rs:17:12
2036
|
2137
LL | const Q<'a>: &'a str;
2238
| ---- lifetimes in impl do not match this const in trait
@@ -25,7 +41,7 @@ LL | const Q = "";
2541
| ^ lifetimes do not match const in trait
2642

2743
error: missing type for `const` item
28-
--> $DIR/assoc-const-missing-type.rs:16:12
44+
--> $DIR/assoc-const-missing-type.rs:17:12
2945
|
3046
LL | const Q = "";
3147
| ^ help: provide a type for the associated constant: `: &str`
@@ -42,7 +58,7 @@ LL | const K<T> = ();
4258
found unit type `()`
4359
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4460

45-
error: aborting due to 5 previous errors
61+
error: aborting due to 6 previous errors
4662

47-
Some errors have detailed explanations: E0195, E0308.
63+
Some errors have detailed explanations: E0195, E0308, E0326.
4864
For more information about an error, try `rustc --explain E0195`.

tests/ui/impl-trait/issues/issue-86642.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
2-
//~^ `impl Trait` is not allowed in static types
2+
//~^ ERROR `impl Trait` is not allowed in static types
3+
//~| ERROR cycle detected when computing type of `x`
4+
//~| ERROR the placeholder `_` is not allowed within types on item signatures for static variables
35
let res = (move |source| Ok(source))(source);
46
let res = res.or((move |source| Ok(source))(source));
57
res

tests/ui/impl-trait/issues/issue-86642.stderr

+33-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,37 @@ LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
66
|
77
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
88

9-
error: aborting due to 1 previous error
9+
error[E0391]: cycle detected when computing type of `x`
10+
--> $DIR/issue-86642.rs:1:1
11+
|
12+
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
|
15+
note: ...which requires type-checking `x`...
16+
--> $DIR/issue-86642.rs:1:1
17+
|
18+
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
note: ...which requires computing the opaque types defined by `x`...
21+
--> $DIR/issue-86642.rs:1:1
22+
|
23+
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
= note: ...which again requires computing type of `x`, completing the cycle
26+
note: cycle used when checking that `x` is well-formed
27+
--> $DIR/issue-86642.rs:1:1
28+
|
29+
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
32+
33+
error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
34+
--> $DIR/issue-86642.rs:1:11
35+
|
36+
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed in type signatures
38+
39+
error: aborting due to 3 previous errors
1040

11-
For more information about this error, try `rustc --explain E0562`.
41+
Some errors have detailed explanations: E0121, E0391, E0562.
42+
For more information about an error, try `rustc --explain E0121`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// A regression test for #124164
2+
// const-eval used to complain because the allocation was mutable (due to the atomic)
3+
// while it expected `{type error}` allocations to be immutable.
4+
5+
static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
6+
//~^ ERROR missing type for `static` item
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: missing type for `static` item
2+
--> $DIR/error-type-interior-mutable.rs:5:16
3+
|
4+
LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
5+
| ^ help: provide a type for the static variable: `AtomicUsize`
6+
7+
error: aborting due to 1 previous error
8+

tests/ui/typeck/typeck_type_placeholder_item.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
583583
--> $DIR/typeck_type_placeholder_item.rs:209:14
584584
|
585585
LL | const D: _ = 42;
586-
| ^ not allowed in type signatures
586+
| ^
587+
| |
588+
| not allowed in type signatures
589+
| help: replace with the correct type: `i32`
587590

588591
error[E0046]: not all trait items implemented, missing: `F`
589592
--> $DIR/typeck_type_placeholder_item.rs:200:1

0 commit comments

Comments
 (0)