diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index cf6027a312fa..f9a86c927653 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::{ ValidationErrorInfo, ValidationErrorKind, ValidationErrorKind::*, }; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{ Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, @@ -724,20 +724,21 @@ fn mutability<'mir, 'tcx: 'mir>( // so just use the declared mutability. mutability } else { + let ty = ecx + .tcx + .type_of(did) + .no_bound_vars() + .expect("statics should not have generic parameters"); let mutability = match mutability { - Mutability::Not - if !ecx - .tcx - .type_of(did) - .no_bound_vars() - .expect("statics should not have generic parameters") - .is_freeze(*ecx.tcx, ty::ParamEnv::reveal_all()) => - { + Mutability::Not if !ty.is_freeze(*ecx.tcx, ty::ParamEnv::reveal_all()) => { Mutability::Mut } _ => mutability, }; - if let Some((_, alloc)) = ecx.memory.alloc_map.get(alloc_id) { + if let Some((_, alloc)) = ecx.memory.alloc_map.get(alloc_id) + // For type errors, we do not know whether they are supposed to be mutable or not. + && !ty.references_error() + { assert_eq!(alloc.mutability, mutability); } mutability diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2f4dcdbdf2b1..ff24271e9904 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2509,6 +2509,24 @@ impl<'hir> Ty<'hir> { _ => false, } } + + pub fn references_error(&self) -> Option { + use crate::intravisit::Visitor; + struct ErrVisitor(Option); + impl<'v> Visitor<'v> for ErrVisitor { + fn visit_ty(&mut self, t: &'v Ty<'v>) { + if let TyKind::Err(guar) = t.kind { + self.0 = Some(guar); + return; + } + crate::intravisit::walk_ty(self, t); + } + } + + let mut err_visitor = ErrVisitor(None); + err_visitor.visit_ty(self); + err_visitor.0 + } } /// Not represented directly in the AST; referred to by name through a `ty_path`. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1475e53c47c2..74b5a03f9a14 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -403,7 +403,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder match item.kind { ItemKind::Static(ty, .., body_id) => { - if ty.is_suggestable_infer_ty() { + if ty.is_suggestable_infer_ty() || ty.references_error().is_some() { infer_placeholder_type( tcx, def_id, @@ -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). @@ -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) { diff --git a/tests/crashes/124164.rs b/tests/crashes/124164.rs deleted file mode 100644 index 8c9b4bddbe80..000000000000 --- a/tests/crashes/124164.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #124164 -static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); - -fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs index 93160f0b5758..df39e90c455e 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.rs +++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs @@ -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 diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr index 6f35c0958d45..20328fd7303c 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr +++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr @@ -15,8 +15,24 @@ error: missing type for `const` item LL | const K = (); | ^ 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 = (); + | - ^ 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; + | ^ + = 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 @@ -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` @@ -42,7 +58,7 @@ LL | const K = (); 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`. diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs index 74be8779d445..463919c415ff 100644 --- a/tests/ui/impl-trait/issues/issue-86642.rs +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -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 diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr index 19fd5bc0c1ca..e97270466d7c 100644 --- a/tests/ui/impl-trait/issues/issue-86642.stderr +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -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`. diff --git a/tests/ui/static/error-type-interior-mutable.rs b/tests/ui/static/error-type-interior-mutable.rs new file mode 100644 index 000000000000..90b19f0d196f --- /dev/null +++ b/tests/ui/static/error-type-interior-mutable.rs @@ -0,0 +1,8 @@ +// A regression test for #124164 +// const-eval used to complain because the allocation was mutable (due to the atomic) +// while it expected `{type error}` allocations to be immutable. + +static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); +//~^ ERROR missing type for `static` item + +fn main() {} diff --git a/tests/ui/static/error-type-interior-mutable.stderr b/tests/ui/static/error-type-interior-mutable.stderr new file mode 100644 index 000000000000..975f9dcaf7d0 --- /dev/null +++ b/tests/ui/static/error-type-interior-mutable.stderr @@ -0,0 +1,8 @@ +error: missing type for `static` item + --> $DIR/error-type-interior-mutable.rs:5:16 + | +LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); + | ^ help: provide a type for the static variable: `AtomicUsize` + +error: aborting due to 1 previous error + diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 7977504dae1d..e907c9ebe923 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -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