Skip to content

Commit

Permalink
Better recover static/const type in type_of
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Noratrieb committed May 25, 2024
1 parent b81adab commit 49f9724
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 11 deletions.
14 changes: 11 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,7 @@ fn infer_placeholder_type<'a>(
// then the user may have written e.g. `const A = 42;`.
// In this case, the parser has stashed a diagnostic for
// us to improve in typeck so we do that now.
let guar = tcx
.dcx()
tcx.dcx()
.try_steal_modify_and_emit_err(span, StashKey::ItemNoType, |err| {
if !ty.references_error() {
// Only suggest adding `:` if it was missing (and suggested by parsing diagnostic).
Expand Down Expand Up @@ -619,7 +618,16 @@ fn infer_placeholder_type<'a>(
}
diag.emit()
});
Ty::new_error(tcx, guar)

// Typeck returns regions as erased. We can't deal with erased regions here though, so we
// turn them into `&'static`, which is *generally* correct for statics and consts.
// Assoc consts can reference generic lifetimes from the parent generics, but treating them
// as static is unlikely to cause issues.
let ty = tcx.fold_regions(ty, |region, _| match region.kind() {
ty::ReErased => tcx.lifetimes.re_static,
_ => region,
});
ty
}

fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
Expand Down
1 change: 1 addition & 0 deletions tests/ui/generic-const-items/assoc-const-missing-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ impl Trait for () {
//~^ ERROR missing type for `const` item
//~| ERROR mismatched types
//~| ERROR mismatched types
//~| ERROR implemented const `K` has an incompatible type for trait
const Q = "";
//~^ ERROR missing type for `const` item
//~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration
Expand Down
24 changes: 20 additions & 4 deletions tests/ui/generic-const-items/assoc-const-missing-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,24 @@ error: missing type for `const` item
LL | const K<T> = ();
| ^ help: provide a type for the associated constant: `()`

error[E0326]: implemented const `K` has an incompatible type for trait
--> $DIR/assoc-const-missing-type.rs:12:15
|
LL | const K<T> = ();
| - ^ expected type parameter `T`, found `()`
| |
| expected this type parameter
|
note: type in trait
--> $DIR/assoc-const-missing-type.rs:7:17
|
LL | const K<T>: T;
| ^
= note: expected type parameter `T`
found unit type `()`

error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration
--> $DIR/assoc-const-missing-type.rs:16:12
--> $DIR/assoc-const-missing-type.rs:17:12
|
LL | const Q<'a>: &'a str;
| ---- lifetimes in impl do not match this const in trait
Expand All @@ -25,7 +41,7 @@ LL | const Q = "";
| ^ lifetimes do not match const in trait

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

error: aborting due to 5 previous errors
error: aborting due to 6 previous errors

Some errors have detailed explanations: E0195, E0308.
Some errors have detailed explanations: E0195, E0308, E0326.
For more information about an error, try `rustc --explain E0195`.
4 changes: 3 additions & 1 deletion tests/ui/impl-trait/issues/issue-86642.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
//~^ `impl Trait` is not allowed in static types
//~^ ERROR `impl Trait` is not allowed in static types
//~| ERROR cycle detected when computing type of `x`
//~| ERROR the placeholder `_` is not allowed within types on item signatures for static variables
let res = (move |source| Ok(source))(source);
let res = res.or((move |source| Ok(source))(source));
res
Expand Down
35 changes: 33 additions & 2 deletions tests/ui/impl-trait/issues/issue-86642.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,37 @@ LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
|
= note: `impl Trait` is only allowed in arguments and return types of functions and methods

error: aborting due to 1 previous error
error[E0391]: cycle detected when computing type of `x`
--> $DIR/issue-86642.rs:1:1
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires type-checking `x`...
--> $DIR/issue-86642.rs:1:1
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires computing the opaque types defined by `x`...
--> $DIR/issue-86642.rs:1:1
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `x`, completing the cycle
note: cycle used when checking that `x` is well-formed
--> $DIR/issue-86642.rs:1:1
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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

error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
--> $DIR/issue-86642.rs:1:11
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed in type signatures

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0562`.
Some errors have detailed explanations: E0121, E0391, E0562.
For more information about an error, try `rustc --explain E0121`.
5 changes: 4 additions & 1 deletion tests/ui/typeck/typeck_type_placeholder_item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
--> $DIR/typeck_type_placeholder_item.rs:209:14
|
LL | const D: _ = 42;
| ^ not allowed in type signatures
| ^
| |
| not allowed in type signatures
| help: replace with the correct type: `i32`

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

0 comments on commit 49f9724

Please sign in to comment.