Rollup merge of #148256 - lcnr:orphan-check, r=spastorino,WaffleLapkin

remove support for `typeof`

see https://github.com/rust-lang/compiler-team/issues/940 closes https://github.com/rust-lang/rust/issues/148700

This also enables checks for invariants previously broken by `typeof` again.

r? types
This commit is contained in:
Matthias Krüger 2025-11-27 15:59:11 +01:00 committed by GitHub
commit d67a12dfff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 40 additions and 332 deletions

View file

@ -2513,8 +2513,6 @@ pub enum TyKind {
ImplTrait(NodeId, #[visitable(extra = BoundKind::Impl)] GenericBounds),
/// No-op; kept solely so that we can pretty-print faithfully.
Paren(Box<Ty>),
/// Unused for now.
Typeof(AnonConst),
/// This means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
Infer,

View file

@ -294,7 +294,6 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
| ast::TyKind::Never
| ast::TyKind::Tup(..)
| ast::TyKind::Paren(..)
| ast::TyKind::Typeof(..)
| ast::TyKind::Infer
| ast::TyKind::ImplicitSelf
| ast::TyKind::CVarArgs

View file

@ -1367,7 +1367,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_ty(ty, itctx),
self.lower_array_length_to_const_arg(length),
),
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
TyKind::TraitObject(bounds, kind) => {
let mut lifetime_bound = None;
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {

View file

@ -1325,11 +1325,6 @@ impl<'a> State<'a> {
self.print_expr(&length.value, FixupContext::default());
self.word("]");
}
ast::TyKind::Typeof(e) => {
self.word("typeof(");
self.print_expr(&e.value, FixupContext::default());
self.word(")");
}
ast::TyKind::Infer => {
self.word("_");
}

View file

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.
The `typeof` keyword is currently reserved but unimplemented.
Erroneous code example:

View file

@ -3680,8 +3680,6 @@ pub enum TyKind<'hir, Unambig = ()> {
/// We use pointer tagging to represent a `&'hir Lifetime` and `TraitObjectSyntax` pair
/// as otherwise this type being `repr(C)` would result in `TyKind` increasing in size.
TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
/// Unused for now.
Typeof(&'hir AnonConst),
/// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed),
/// Pattern types (`pattern_type!(u32 is 1..)`)

View file

@ -1029,7 +1029,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -
}
try_visit!(visitor.visit_lifetime(lifetime));
}
TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
TyKind::InferDelegation(..) | TyKind::Err(_) => {}
TyKind::Pat(ty, pat) => {
try_visit!(visitor.visit_ty_unambig(ty));

View file

@ -552,11 +552,6 @@ hir_analysis_ty_param_some = type parameter `{$param}` must be used as the type
hir_analysis_type_of = {$ty}
hir_analysis_typeof_reserved_keyword_used =
`typeof` is a reserved keyword but unimplemented
.suggestion = consider replacing `typeof(...)` with an actual type
.label = reserved keyword
hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates
.label = unconstrained {$param_def_kind}
.const_param_note = expressions using a const parameter must map each value to a distinct output value

View file

@ -195,10 +195,11 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => {
Err(self.tcx.dcx().delayed_bug("cannot define inherent `impl` for closure types"))
}
ty::Alias(ty::Free, _) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
| ty::CoroutineWitness(..)
| ty::Alias(ty::Free, _)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
}
// We could bail out here, but that will silence other useful errors.

View file

@ -217,21 +217,19 @@ pub(crate) fn orphan_check_impl(
| ty::Slice(..)
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Never
| ty::Tuple(..)
| ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
ty::Closure(..)
ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => {
return Err(tcx
.dcx()
.delayed_bug("cannot define inherent `impl` for closure types"));
}
ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
| ty::CoroutineWitness(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..) => {
let sp = tcx.def_span(impl_def_id);
span_bug!(sp, "weird self type for autotrait impl")
}

View file

@ -7,15 +7,12 @@ use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{
self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions,
};
use rustc_middle::ty::{self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Ident, Span};
use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder};
use crate::check::wfcheck::check_static_item;
use crate::errors::TypeofReservedKeywordUsed;
use crate::hir_ty_lowering::HirTyLowerer;
mod opaque;
@ -48,21 +45,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
}
// Sort of affects the type system, but only for the purpose of diagnostics
// so no need for ConstArg.
Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
let ty = fold_regions(tcx, ty, |r, _| {
if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
});
let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) {
(ty, Some((span, Applicability::MachineApplicable)))
} else {
(ty, None)
};
tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
return ty;
}
Node::Field(&hir::FieldDef { default: Some(c), def_id: field_def_id, .. })
if c.hir_id == hir_id =>

View file

@ -378,17 +378,6 @@ pub(crate) struct ParenthesizedFnTraitExpansion {
pub expanded_type: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)]
pub(crate) struct TypeofReservedKeywordUsed<'tcx> {
pub ty: Ty<'tcx>,
#[primary_span]
#[label]
pub span: Span,
#[suggestion(style = "verbose", code = "{ty}")]
pub opt_sugg: Option<(Span, Applicability)>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)]
pub(crate) struct ValueOfAssociatedStructAlreadySpecified {

View file

@ -2582,7 +2582,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let length = self.lower_const_arg(length, FeedConstTy::No);
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
}
hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(),
hir::TyKind::Infer(()) => {
// Infer also appears as the type of arguments or return
// values in an ExprKind::Closure, or as

View file

@ -445,11 +445,6 @@ impl<'a> State<'a> {
self.print_const_arg(length);
self.word("]");
}
hir::TyKind::Typeof(ref e) => {
self.word("typeof(");
self.print_anon_const(e);
self.word(")");
}
hir::TyKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");

View file

@ -296,11 +296,6 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
} else if let Node::AnonConst(_) = node {
let id = tcx.local_def_id_to_hir_id(def_id);
match tcx.parent_hir_node(id) {
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(anon_const), span, .. })
if anon_const.hir_id == id =>
{
Some(fcx.next_ty_var(span))
}
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => {
asm.operands.iter().find_map(|(op, _op_sp)| match op {

View file

@ -1660,18 +1660,6 @@ impl EarlyLintPass for UnusedBraces {
);
}
ast::TyKind::Typeof(ref anon_const) => {
self.check_unused_delims_expr(
cx,
&anon_const.value,
UnusedDelimsCtx::AnonConst,
false,
None,
None,
false,
);
}
_ => {}
}
}

View file

@ -336,7 +336,6 @@ where
| ty::Uint(..)
| ty::Float(..)
| ty::Str
| ty::FnDef(..)
| ty::Pat(..)
| ty::FnPtr(..)
| ty::Array(..)
@ -403,7 +402,6 @@ where
// implement, so we don't use this behavior.
// Addendum: Moreover, revealing the underlying type is likely to cause cycle
// errors as we rely on coherence / the specialization graph during typeck.
self.found_non_local_ty(ty)
}
}
@ -435,31 +433,14 @@ where
}
}
ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
ty::Closure(did, ..) => {
if self.def_id_is_local(did) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else {
self.found_non_local_ty(ty)
}
ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => {
unreachable!("unnameable type in coherence: {ty:?}");
}
ty::CoroutineClosure(did, ..) => {
if self.def_id_is_local(did) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else {
self.found_non_local_ty(ty)
}
}
ty::Coroutine(did, ..) => {
if self.def_id_is_local(did) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else {
self.found_non_local_ty(ty)
}
}
// This should only be created when checking whether we have to check whether some
// auto trait impl applies. There will never be multiple impls, so we can just
// act as if it were a local type here.
ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
};
// A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
// the first type we visit is always the self type.

View file

@ -7,7 +7,7 @@ use rustc_ast::{
TyKind, UnsafeBinderTy,
};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, Diag, PResult};
use rustc_errors::{Applicability, Diag, E0516, PResult};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};
@ -328,7 +328,7 @@ impl<'a> Parser<'a> {
self.expect_and()?;
self.parse_borrowed_pointee()?
} else if self.eat_keyword_noexpect(kw::Typeof) {
self.parse_typeof_ty()?
self.parse_typeof_ty(lo)?
} else if self.eat_keyword(exp!(Underscore)) {
// A type to be inferred `_`
TyKind::Infer
@ -784,13 +784,20 @@ impl<'a> Parser<'a> {
}
}
// Parses the `typeof(EXPR)`.
// To avoid ambiguity, the type is surrounded by parentheses.
fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
/// Parses the `typeof(EXPR)` for better diagnostics before returning
/// an error type.
fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
self.expect(exp!(OpenParen))?;
let expr = self.parse_expr_anon_const()?;
let _expr = self.parse_expr_anon_const()?;
self.expect(exp!(CloseParen))?;
Ok(TyKind::Typeof(expr))
let span = lo.to(self.prev_token.span);
let guar = self
.dcx()
.struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")
.with_note("consider replacing `typeof(...)` with an actual type")
.with_code(E0516)
.emit();
Ok(TyKind::Err(guar))
}
/// Parses a function pointer type (`TyKind::FnPtr`).

View file

@ -408,7 +408,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
OpaqueDef,
TraitAscription,
TraitObject,
Typeof,
Infer,
Pat,
Err
@ -683,7 +682,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
TraitObject,
ImplTrait,
Paren,
Typeof,
Infer,
ImplicitSelf,
MacCall,

View file

@ -954,9 +954,6 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
self.visit_ty(element_ty);
self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
}
TyKind::Typeof(ct) => {
self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
}
_ => visit::walk_ty(self, ty),
}
self.diag_metadata.current_trait_object = prev;

View file

@ -1841,7 +1841,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer(())
| TyKind::Err(_)
| TyKind::Typeof(..)
| TyKind::InferDelegation(..)
| TyKind::TraitAscription(_) => Infer,
}

View file

@ -830,7 +830,6 @@ impl TyCoercionStability {
TyKind::OpaqueDef(..)
| TyKind::TraitAscription(..)
| TyKind::Infer(())
| TyKind::Typeof(..)
| TyKind::TraitObject(..)
| TyKind::InferDelegation(..)
| TyKind::Err(_) => Self::Reborrow,
@ -911,7 +910,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
}
fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
if self.0 || matches!(ty.kind, TyKind::OpaqueDef(..) | TyKind::Typeof(_) | TyKind::Err(_)) {
if self.0 || matches!(ty.kind, TyKind::OpaqueDef(..) | TyKind::Err(_)) {
self.0 = true;
} else {
walk_ty(self, ty);

View file

@ -875,7 +875,6 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
(Path(lq, lp), Path(rq, rp)) => both(lq.as_deref(), rq.as_deref(), eq_qself) && eq_path(lp, rp),
(TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
(ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, eq_generic_bound),
(Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
_ => false,
}

View file

@ -524,11 +524,10 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) {
TyKind::ImplicitSelf
// experimental
|TyKind::Pat(..)
| TyKind::Pat(..)
// unused
| TyKind::CVarArgs
| TyKind::Typeof(_)
// placeholder
| TyKind::Dummy

View file

@ -1309,9 +1309,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::TraitObject(_, lifetime) => {
self.hash_lifetime(lifetime);
},
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
TyKind::UnsafeBinder(binder) => {
self.hash_ty(binder.inner_ty);
},

View file

@ -8,8 +8,7 @@ use crate::comment::{combine_strs_with_missing_comments, contains_comment};
use crate::config::lists::*;
use crate::config::{IndentStyle, StyleEdition, TypeDensity};
use crate::expr::{
ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple,
rewrite_unary_prefix,
ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix,
};
use crate::lists::{
ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
@ -1031,13 +1030,6 @@ impl Rewrite for ast::Ty {
}
ast::TyKind::CVarArgs => Ok("...".to_owned()),
ast::TyKind::Dummy | ast::TyKind::Err(_) => Ok(context.snippet(self.span).to_owned()),
ast::TyKind::Typeof(ref anon_const) => rewrite_call(
context,
"typeof",
&[anon_const.value.clone()],
self.span,
shape,
),
ast::TyKind::Pat(ref ty, ref pat) => {
let ty = ty.rewrite_result(context, shape)?;
let pat = pat.rewrite_result(context, shape)?;

View file

@ -158,9 +158,3 @@ impl<T: [ const] Trait> Foo<T> {
Self(t)
}
}
// #4357
type T = typeof(
1);
impl T for .. {
}

View file

@ -167,7 +167,3 @@ impl<T: [const] Trait> Foo<T> {
Self(t)
}
}
// #4357
type T = typeof(1);
impl T for .. {}

View file

@ -2983,9 +2983,6 @@ ui/typeck/issue-96530.rs
ui/typeck/issue-96738.rs
ui/typeck/issue-98260.rs
ui/typeck/issue-98982.rs
ui/typeof/issue-100183.rs
ui/typeof/issue-29184.rs
ui/typeof/issue-42060.rs
ui/unboxed-closures/issue-18652.rs
ui/unboxed-closures/issue-18661.rs
ui/unboxed-closures/issue-30906.rs

View file

@ -1,5 +0,0 @@
// https://github.com/rust-lang/rust/issues/102986
struct Struct {
y: (typeof("hey"),),
//~^ ERROR `typeof` is a reserved keyword but unimplemented
}

View file

@ -1,15 +0,0 @@
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/ice-typeof-102986.rs:3:9
|
LL | y: (typeof("hey"),),
| ^^^^^^^^^^^^^ reserved keyword
|
help: consider replacing `typeof(...)` with an actual type
|
LL - y: (typeof("hey"),),
LL + y: (&str,),
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0516`.

View file

@ -1,7 +0,0 @@
impl typeof(|| {}) {}
//~^ ERROR `typeof` is a reserved keyword but unimplemented
unsafe impl Send for typeof(|| {}) {}
//~^ ERROR `typeof` is a reserved keyword but unimplemented
fn main() {}

View file

@ -1,15 +0,0 @@
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/impl-closure-147146.rs:1:6
|
LL | impl typeof(|| {}) {}
| ^^^^^^^^^^^^^ reserved keyword
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/impl-closure-147146.rs:4:22
|
LL | unsafe impl Send for typeof(|| {}) {}
| ^^^^^^^^^^^^^ reserved keyword
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0516`.

View file

@ -1,4 +1,3 @@
fn main() {
let x: typeof(92) = 92; //~ ERROR E0516
//~| NOTE reserved keyword
}

View file

@ -2,13 +2,9 @@ error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/E0516.rs:2:12
|
LL | let x: typeof(92) = 92;
| ^^^^^^^^^^ reserved keyword
|
help: consider replacing `typeof(...)` with an actual type
|
LL - let x: typeof(92) = 92;
LL + let x: i32 = 92;
| ^^^^^^^^^^
|
= note: consider replacing `typeof(...)` with an actual type
error: aborting due to 1 previous error

View file

@ -1,6 +0,0 @@
struct Struct {
y: (typeof("hey"),),
//~^ ERROR `typeof` is a reserved keyword but unimplemented
}
fn main() {}

View file

@ -1,15 +0,0 @@
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/issue-100183.rs:2:9
|
LL | y: (typeof("hey"),),
| ^^^^^^^^^^^^^ reserved keyword
|
help: consider replacing `typeof(...)` with an actual type
|
LL - y: (typeof("hey"),),
LL + y: (&str,),
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0516`.

View file

@ -1,3 +0,0 @@
fn main() {
let x: typeof(92) = 92; //~ ERROR `typeof` is a reserved keyword
}

View file

@ -1,15 +0,0 @@
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/issue-29184.rs:2:12
|
LL | let x: typeof(92) = 92;
| ^^^^^^^^^^ reserved keyword
|
help: consider replacing `typeof(...)` with an actual type
|
LL - let x: typeof(92) = 92;
LL + let x: i32 = 92;
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0516`.

View file

@ -1,11 +0,0 @@
fn main() {
let thing = ();
let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant
//~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516]
}
fn f(){
let q = 1;
<typeof(q)>::N //~ ERROR attempt to use a non-constant value in a constant
//~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516]
}

View file

@ -1,40 +0,0 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-42060.rs:3:23
|
LL | let other: typeof(thing) = thing;
| ^^^^^ non-constant value
|
help: consider using `const` instead of `let`
|
LL - let thing = ();
LL + const thing: /* Type */ = ();
|
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-42060.rs:9:13
|
LL | <typeof(q)>::N
| ^ non-constant value
|
help: consider using `const` instead of `let`
|
LL - let q = 1;
LL + const q: /* Type */ = 1;
|
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/issue-42060.rs:3:16
|
LL | let other: typeof(thing) = thing;
| ^^^^^^^^^^^^^ reserved keyword
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/issue-42060.rs:9:6
|
LL | <typeof(q)>::N
| ^^^^^^^^^ reserved keyword
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0435, E0516.
For more information about an error, try `rustc --explain E0435`.

View file

@ -1,12 +0,0 @@
// Test that using typeof results in the correct type mismatch errors instead of always assuming
// `usize`, in addition to the pre-existing "typeof is reserved and unimplemented" error
//@ dont-require-annotations: NOTE
fn main() {
const a: u8 = 1;
let b: typeof(a) = 1i8;
//~^ ERROR `typeof` is a reserved keyword but unimplemented
//~| ERROR mismatched types
//~| NOTE expected `u8`, found `i8`
}

View file

@ -1,30 +0,0 @@
error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/type_mismatch.rs:8:12
|
LL | let b: typeof(a) = 1i8;
| ^^^^^^^^^ reserved keyword
|
help: consider replacing `typeof(...)` with an actual type
|
LL - let b: typeof(a) = 1i8;
LL + let b: u8 = 1i8;
|
error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:8:24
|
LL | let b: typeof(a) = 1i8;
| --------- ^^^ expected `u8`, found `i8`
| |
| expected due to this
|
help: change the type of the numeric literal from `i8` to `u8`
|
LL - let b: typeof(a) = 1i8;
LL + let b: typeof(a) = 1u8;
|
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0308, E0516.
For more information about an error, try `rustc --explain E0308`.