mGCA: Validate const literal against expected type

Co-authored-by: Boxy <rust@boxyuwu.dev>
This commit is contained in:
reddevilmidzy 2026-02-03 01:08:44 +09:00
parent 381e9ef09e
commit 8af02e230a
25 changed files with 407 additions and 136 deletions

View file

@ -35,7 +35,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::DynCompatibilityViolation;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::mir::interpret::{LitToConstInput, const_lit_matches_ty};
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt,
@ -2803,8 +2803,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
) -> Const<'tcx> {
let tcx = self.tcx();
if let LitKind::Err(guar) = *kind {
return ty::Const::new_error(tcx, guar);
}
let input = LitToConstInput { lit: *kind, ty, neg };
tcx.at(span).lit_to_const(input)
match tcx.at(span).lit_to_const(input) {
Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty),
None => {
let e = tcx.dcx().span_err(span, "type annotations needed for the literal");
ty::Const::new_error(tcx, e)
}
}
}
#[instrument(skip(self), level = "debug")]
@ -2833,11 +2842,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
_ => None,
};
lit_input
// Allow the `ty` to be an alias type, though we cannot handle it here, we just go through
// the more expensive anon const code path.
.filter(|l| !l.ty.has_aliases())
.map(|l| tcx.at(expr.span).lit_to_const(l))
lit_input.and_then(|l| {
if const_lit_matches_ty(tcx, &l.lit, l.ty, l.neg) {
tcx.at(expr.span)
.lit_to_const(l)
.map(|value| ty::Const::new_value(tcx, value.valtree, value.ty))
} else {
None
}
})
}
fn require_type_const_attribute(

View file

@ -84,6 +84,44 @@ pub struct LitToConstInput<'tcx> {
pub neg: bool,
}
pub fn const_lit_matches_ty<'tcx>(
tcx: TyCtxt<'tcx>,
kind: &LitKind,
ty: Ty<'tcx>,
neg: bool,
) -> bool {
match (*kind, ty.kind()) {
(LitKind::Str(..), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => true,
(LitKind::Str(..), ty::Str) if tcx.features().deref_patterns() => true,
(LitKind::ByteStr(..), ty::Ref(_, inner_ty, _))
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
&& matches!(ty.kind(), ty::Uint(ty::UintTy::U8)) =>
{
true
}
(LitKind::ByteStr(..), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
if tcx.features().deref_patterns()
&& matches!(inner_ty.kind(), ty::Uint(ty::UintTy::U8)) =>
{
true
}
(LitKind::Byte(..), ty::Uint(ty::UintTy::U8)) => true,
(LitKind::CStr(..), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Adt(def, _)
if tcx.is_lang_item(def.did(), rustc_hir::LangItem::CStr)) =>
{
true
}
(LitKind::Int(..), ty::Uint(_)) if !neg => true,
(LitKind::Int(..), ty::Int(_)) => true,
(LitKind::Bool(..), ty::Bool) => true,
(LitKind::Float(..), ty::Float(_)) => true,
(LitKind::Char(..), ty::Char) => true,
(LitKind::Err(..), _) => true,
_ => false,
}
}
#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct AllocId(pub NonZero<u64>);

View file

@ -1412,7 +1412,7 @@ rustc_queries! {
// FIXME get rid of this with valtrees
query lit_to_const(
key: LitToConstInput<'tcx>
) -> ty::Const<'tcx> {
) -> Option<ty::Value<'tcx>> {
desc { "converting literal to const" }
}

View file

@ -256,6 +256,10 @@ impl Erasable for Option<ty::EarlyBinder<'_, Ty<'_>>> {
type Storage = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
}
impl Erasable for Option<ty::Value<'_>> {
type Storage = [u8; size_of::<Option<ty::Value<'static>>>()];
}
impl Erasable for rustc_hir::MaybeOwner<'_> {
type Storage = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
}

View file

@ -3,7 +3,7 @@ use rustc_ast::{self as ast, UintTy};
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _};
use tracing::trace;
use crate::builder::parse_float_into_scalar;
@ -11,11 +11,11 @@ use crate::builder::parse_float_into_scalar;
pub(crate) fn lit_to_const<'tcx>(
tcx: TyCtxt<'tcx>,
lit_input: LitToConstInput<'tcx>,
) -> ty::Const<'tcx> {
let LitToConstInput { lit, ty, neg } = lit_input;
) -> Option<ty::Value<'tcx>> {
let LitToConstInput { lit, ty: expected_ty, neg } = lit_input;
if let Err(guar) = ty.error_reported() {
return ty::Const::new_error(tcx, guar);
if expected_ty.error_reported().is_err() {
return None;
}
let trunc = |n, width: ty::UintTy| {
@ -32,22 +32,17 @@ pub(crate) fn lit_to_const<'tcx>(
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))
};
let valtree = match (lit, ty.kind()) {
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
let (valtree, valtree_ty) = match (lit, expected_ty.kind()) {
(ast::LitKind::Str(s, _), _) => {
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
}
(ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => {
// String literal patterns may have type `str` if `deref_patterns` is enabled, in order
// to allow `deref!("..."): String`.
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
(ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
}
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
&& let ty::Uint(UintTy::U8) = ty.kind() =>
{
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
}
(ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
if tcx.features().deref_patterns()
@ -55,40 +50,66 @@ pub(crate) fn lit_to_const<'tcx>(
{
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str())
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
}
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
ty::ValTree::from_scalar_int(tcx, n.into())
(ast::LitKind::ByteStr(byte_sym, _), _) => {
let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
let valtree_ty = Ty::new_array(tcx, tcx.types.u8, byte_sym.as_byte_str().len() as u64);
(valtree, valtree_ty)
}
(ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
(ast::LitKind::Byte(n), _) => (ty::ValTree::from_scalar_int(tcx, n.into()), tcx.types.u8),
(ast::LitKind::CStr(byte_sym, _), _)
if let Some(cstr_def_id) = tcx.lang_items().get(LangItem::CStr) =>
{
// A CStr is a newtype around a byte slice, so we create the inner slice here.
// We need a branch for each "level" of the data structure.
let cstr_ty = tcx.type_of(cstr_def_id).skip_binder();
let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, *inner_ty)])
let valtree =
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, cstr_ty)]);
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, cstr_ty);
(valtree, valtree_ty)
}
(ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => {
(ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => {
let scalar_int = trunc(n.get(), ui);
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui))
}
(ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None,
(ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => {
let scalar_int =
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
}
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => {
let scalar_int = trunc(n.get(), *ui);
ty::ValTree::from_scalar_int(tcx, scalar_int)
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
}
(ast::LitKind::Int(n, _), ty::Int(i)) => {
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => {
// Unsigned "negation" has the same bitwise effect as signed negation,
// which gets the result we want without additional casts.
let scalar_int =
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
ty::ValTree::from_scalar_int(tcx, scalar_int)
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i))
}
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()),
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
let bits = parse_float_into_scalar(n, *fty, neg).unwrap_or_else(|| {
tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit))
});
ty::ValTree::from_scalar_int(tcx, bits)
(ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool),
(ast::LitKind::Float(n, ast::LitFloatType::Suffixed(fty)), _) => {
let fty = match fty {
ast::FloatTy::F16 => ty::FloatTy::F16,
ast::FloatTy::F32 => ty::FloatTy::F32,
ast::FloatTy::F64 => ty::FloatTy::F64,
ast::FloatTy::F128 => ty::FloatTy::F128,
};
let bits = parse_float_into_scalar(n, fty, neg)?;
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
}
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()),
(ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, guar),
_ => return ty::Const::new_misc_error(tcx),
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => {
let bits = parse_float_into_scalar(n, *fty, neg)?;
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
}
(ast::LitKind::Char(c), _) => (ty::ValTree::from_scalar_int(tcx, c.into()), tcx.types.char),
(ast::LitKind::Err(_), _) => return None,
_ => return None,
};
ty::Const::new_value(tcx, valtree, ty)
Some(ty::Value { ty: valtree_ty, valtree })
}

View file

@ -8,13 +8,14 @@ use std::cmp::Ordering;
use std::sync::Arc;
use rustc_abi::{FieldIdx, Integer};
use rustc_ast::LitKind;
use rustc_data_structures::assert_matches;
use rustc_errors::codes::*;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, RangeEnd};
use rustc_index::Idx;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::mir::interpret::{LitToConstInput, const_lit_matches_ty};
use rustc_middle::thir::{
Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
};
@ -197,8 +198,6 @@ impl<'tcx> PatCtxt<'tcx> {
expr: Option<&'tcx hir::PatExpr<'tcx>>,
ty: Ty<'tcx>,
) -> Result<(), ErrorGuaranteed> {
use rustc_ast::ast::LitKind;
let Some(expr) = expr else {
return Ok(());
};
@ -696,7 +695,17 @@ impl<'tcx> PatCtxt<'tcx> {
let pat_ty = self.typeck_results.node_type(pat.hir_id);
let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated };
let constant = self.tcx.at(expr.span).lit_to_const(lit_input);
let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
.then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
.flatten()
.map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty))
.unwrap_or_else(|| {
ty::Const::new_error_with_message(
self.tcx,
expr.span,
"literal does not match expected type",
)
});
self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span)
}
}

View file

@ -59,7 +59,10 @@ fn recurse_build<'tcx>(
}
&ExprKind::Literal { lit, neg } => {
let sp = node.span;
tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg })
match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg }) {
Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty),
None => ty::Const::new_misc_error(tcx),
}
}
&ExprKind::NonHirLiteral { lit, user_ty: _ } => {
let val = ty::ValTree::from_scalar_int(tcx, lit);

View file

@ -8,7 +8,7 @@
struct ConstBytes<const T: &'static [*mut u8; 3]>
//~^ ERROR rustc_dump_predicates
//~| NOTE Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] }
//~| NOTE Binder { value: TraitPredicate(<ConstBytes<{const error}> as std::marker::Sized>, polarity:Positive), bound_vars: [] }
//~| NOTE Binder { value: TraitPredicate(<ConstBytes<b"AAA"> as std::marker::Sized>, polarity:Positive), bound_vars: [] }
where
ConstBytes<b"AAA">: Sized;
//~^ ERROR mismatched types

View file

@ -1,12 +1,3 @@
error: rustc_dump_predicates
--> $DIR/byte-string-u8-validation.rs:8:1
|
LL | struct ConstBytes<const T: &'static [*mut u8; 3]>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] }
= note: Binder { value: TraitPredicate(<ConstBytes<{const error}> as std::marker::Sized>, polarity:Positive), bound_vars: [] }
error[E0308]: mismatched types
--> $DIR/byte-string-u8-validation.rs:13:16
|
@ -16,6 +7,15 @@ LL | ConstBytes<b"AAA">: Sized;
= note: expected reference `&'static [*mut u8; 3]`
found reference `&'static [u8; 3]`
error: rustc_dump_predicates
--> $DIR/byte-string-u8-validation.rs:8:1
|
LL | struct ConstBytes<const T: &'static [*mut u8; 3]>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] }
= note: Binder { value: TraitPredicate(<ConstBytes<b"AAA"> as std::marker::Sized>, polarity:Positive), bound_vars: [] }
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -7,15 +7,6 @@ LL | struct ConstBytes<const T: &'static [*mut u8; 3]>;
= note: `*mut u8` must implement `ConstParamTy_`, but it does not
= note: `[*mut u8; 3]` must implement `ConstParamTy_`, but it does not
error[E0308]: mismatched types
--> $DIR/mismatch-raw-ptr-in-adt.rs:9:46
|
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
| ^^^^^^ expected `&[*mut u8; 3]`, found `&[u8; 3]`
|
= note: expected reference `&'static [*mut u8; 3]`
found reference `&'static [u8; 3]`
error[E0308]: mismatched types
--> $DIR/mismatch-raw-ptr-in-adt.rs:9:23
|
@ -25,6 +16,15 @@ LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
= note: expected reference `&'static [*mut u8; 3]`
found reference `&'static [u8; 3]`
error[E0308]: mismatched types
--> $DIR/mismatch-raw-ptr-in-adt.rs:9:46
|
LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
| ^^^^^^ expected `&[*mut u8; 3]`, found `&[u8; 3]`
|
= note: expected reference `&'static [*mut u8; 3]`
found reference `&'static [u8; 3]`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0308, E0741.

View file

@ -0,0 +1,20 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/150983>
#![expect(incomplete_features)]
#![feature(
generic_const_items,
generic_const_parameter_types,
min_generic_const_args,
unsized_const_params
)]
use std::marker::ConstParamTy_;
struct Foo<T> {
field: T,
}
#[type_const]
const WRAP<T : ConstParamTy_> : T = {
Foo::<T>{field : 1} //~ ERROR: type annotations needed for the literal
};
fn main() {}

View file

@ -0,0 +1,8 @@
error: type annotations needed for the literal
--> $DIR/generic_const_type_mismatch.rs:17:22
|
LL | Foo::<T>{field : 1}
| ^
error: aborting due to 1 previous error

View file

@ -0,0 +1,26 @@
#![feature(adt_const_params, min_generic_const_args)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;
#[derive(Eq, PartialEq, ConstParamTy)]
struct Foo {
field: isize
}
fn foo<const F: Foo>() {}
fn main() {
foo::<{ Foo { field: -1_usize } }>();
//~^ ERROR: type annotations needed for the literal
foo::<{ Foo { field: { -1_usize } } }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
foo::<{ Foo { field: -true } }>();
//~^ ERROR: the constant `true` is not of type `isize`
foo::<{ Foo { field: { -true } } }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
foo::<{ Foo { field: -"<3" } }>();
//~^ ERROR: the constant `"<3"` is not of type `isize`
foo::<{ Foo { field: { -"<3" } } }>();
//~^ ERROR: complex const arguments must be placed inside of a `const` block
}

View file

@ -0,0 +1,38 @@
error: complex const arguments must be placed inside of a `const` block
--> $DIR/nonsensical-negated-literal.rs:16:26
|
LL | foo::<{ Foo { field: { -1_usize } } }>();
| ^^^^^^^^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/nonsensical-negated-literal.rs:20:26
|
LL | foo::<{ Foo { field: { -true } } }>();
| ^^^^^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/nonsensical-negated-literal.rs:24:26
|
LL | foo::<{ Foo { field: { -"<3" } } }>();
| ^^^^^^^^^
error: type annotations needed for the literal
--> $DIR/nonsensical-negated-literal.rs:14:26
|
LL | foo::<{ Foo { field: -1_usize } }>();
| ^^^^^^^^
error: the constant `true` is not of type `isize`
--> $DIR/nonsensical-negated-literal.rs:18:13
|
LL | foo::<{ Foo { field: -true } }>();
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool`
error: the constant `"<3"` is not of type `isize`
--> $DIR/nonsensical-negated-literal.rs:22:13
|
LL | foo::<{ Foo { field: -"<3" } }>();
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&'static str`
error: aborting due to 6 previous errors

View file

@ -0,0 +1,22 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/151625>
#![expect(incomplete_features)]
#![feature(
adt_const_params,
min_generic_const_args,
unsized_const_params
)]
fn foo<const X: (bool, i32)>() {}
fn bar<const Y: ([u8; 2], i32)>() {}
fn qux<const Z: (char, i32)>() {}
fn main() {
foo::<{ (1, true) }>();
//~^ ERROR: type annotations needed for the literal
//~| ERROR: mismatched types: expected `i32`, found `bool`
bar::<{ (1_u32, [1, 2]) }>();
//~^ ERROR: expected `i32`, found const array
//~| ERROR: mismatched types: expected `[u8; 2]`, found `u32`
qux::<{ (1i32, 'a') }>();
//~^ ERROR: mismatched types: expected `char`, found `i32`
//~| ERROR: mismatched types: expected `i32`, found `char`
}

View file

@ -0,0 +1,38 @@
error: type annotations needed for the literal
--> $DIR/tuple_expr_type_mismatch.rs:13:14
|
LL | foo::<{ (1, true) }>();
| ^
error: mismatched types: expected `i32`, found `bool`
--> $DIR/tuple_expr_type_mismatch.rs:13:17
|
LL | foo::<{ (1, true) }>();
| ^^^^
error: mismatched types: expected `[u8; 2]`, found `u32`
--> $DIR/tuple_expr_type_mismatch.rs:16:14
|
LL | bar::<{ (1_u32, [1, 2]) }>();
| ^^^^^
error: expected `i32`, found const array
--> $DIR/tuple_expr_type_mismatch.rs:16:21
|
LL | bar::<{ (1_u32, [1, 2]) }>();
| ^^^^^^
error: mismatched types: expected `char`, found `i32`
--> $DIR/tuple_expr_type_mismatch.rs:19:14
|
LL | qux::<{ (1i32, 'a') }>();
| ^^^^
error: mismatched types: expected `i32`, found `char`
--> $DIR/tuple_expr_type_mismatch.rs:19:20
|
LL | qux::<{ (1i32, 'a') }>();
| ^^^
error: aborting due to 6 previous errors

View file

@ -5,7 +5,6 @@ type const FREE: u32 = 5_usize;
//~^ ERROR mismatched types
type const FREE2: isize = FREE;
//~^ ERROR the constant `5` is not of type `isize`
trait Tr {
type const N: usize;

View file

@ -1,9 +1,3 @@
error: the constant `5` is not of type `isize`
--> $DIR/type_const-mismatched-types.rs:7:1
|
LL | type const FREE2: isize = FREE;
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32`
error[E0308]: mismatched types
--> $DIR/type_const-mismatched-types.rs:4:24
|
@ -17,11 +11,11 @@ LL + type const FREE: u32 = 5_u32;
|
error[E0308]: mismatched types
--> $DIR/type_const-mismatched-types.rs:15:27
--> $DIR/type_const-mismatched-types.rs:18:22
|
LL | type const N: usize = false;
| ^^^^^ expected `usize`, found `bool`
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,4 +1,28 @@
error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
|
LL | get_flag::<false, 0xFF>();
| ^^^^ expected `char`, found `u8`
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:33:14
|
LL | get_flag::<7, 'c'>();
| ^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:14
|
LL | get_flag::<42, 0x5ad>();
| ^^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:18
|
LL | get_flag::<42, 0x5ad>();
| ^^^^^ expected `char`, found `u8`
error[E0080]: reading memory at ALLOC6[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:40:32
|
LL | get_flag::<false, { unsafe { char_raw.character } }>();
@ -30,7 +54,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character
42 │ B
}
error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
error[E0080]: reading memory at ALLOC12[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:44:58
|
LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
@ -40,30 +64,6 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character
ff __ __ __ │ .░░░
}
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
|
LL | get_flag::<false, 0xFF>();
| ^^^^ expected `char`, found `u8`
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:33:14
|
LL | get_flag::<7, 'c'>();
| ^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:14
|
LL | get_flag::<42, 0x5ad>();
| ^^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:18
|
LL | get_flag::<42, 0x5ad>();
| ^^^^^ expected `char`, found `u8`
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0080, E0308.

View file

@ -1,3 +1,27 @@
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
|
LL | get_flag::<false, 0xFF>();
| ^^^^ expected `char`, found `u8`
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:33:14
|
LL | get_flag::<7, 'c'>();
| ^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:14
|
LL | get_flag::<42, 0x5ad>();
| ^^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:18
|
LL | get_flag::<42, 0x5ad>();
| ^^^^^ expected `char`, found `u8`
error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory
--> $DIR/invalid-patterns.rs:40:32
|
@ -40,30 +64,6 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character
ff __ __ __ │ .░░░
}
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:31:21
|
LL | get_flag::<false, 0xFF>();
| ^^^^ expected `char`, found `u8`
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:33:14
|
LL | get_flag::<7, 'c'>();
| ^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:14
|
LL | get_flag::<42, 0x5ad>();
| ^^ expected `bool`, found integer
error[E0308]: mismatched types
--> $DIR/invalid-patterns.rs:35:18
|
LL | get_flag::<42, 0x5ad>();
| ^^^^^ expected `char`, found `u8`
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0080, E0308.

View file

@ -6,6 +6,7 @@ trait Trait<T> {
pub struct Foo<T = Box<dyn Trait<DefaultFoo>>>; //~ ERROR cycle detected
//~^ ERROR `T` is never used
//~| ERROR cycle detected
type DefaultFoo = Foo;
fn main() {

View file

@ -5,7 +5,26 @@ LL | pub struct Foo<T = Box<dyn Trait<DefaultFoo>>>;
| ^^^^^^^^^^
|
note: ...which requires expanding type alias `DefaultFoo`...
--> $DIR/issue-34373.rs:9:19
--> $DIR/issue-34373.rs:10:1
|
LL | type DefaultFoo = Foo;
| ^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `Foo::T`, completing the cycle
note: cycle used when checking that `Foo` is well-formed
--> $DIR/issue-34373.rs:7:1
|
LL | pub struct Foo<T = Box<dyn Trait<DefaultFoo>>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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[E0391]: cycle detected when computing type of `Foo::T`
--> $DIR/issue-34373.rs:7:34
|
LL | pub struct Foo<T = Box<dyn Trait<DefaultFoo>>>;
| ^^^^^^^^^^
|
note: ...which requires expanding type alias `DefaultFoo`...
--> $DIR/issue-34373.rs:10:19
|
LL | type DefaultFoo = Foo;
| ^^^
@ -26,7 +45,7 @@ LL | pub struct Foo<T = Box<dyn Trait<DefaultFoo>>>;
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0391, E0392.
For more information about an error, try `rustc --explain E0391`.

View file

@ -16,12 +16,6 @@ error[E0308]: mismatched types
LL | let b = [0; ()];
| ^^ expected `usize`, found `()`
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:33:17
|
LL | let g = [0; G { g: () }];
| ^^^^^^^^^^^ expected `usize`, found `G`
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:12:17
|
@ -68,6 +62,12 @@ LL - let f = [0; 4u8];
LL + let f = [0; 4usize];
|
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:33:17
|
LL | let g = [0; G { g: () }];
| ^^^^^^^^^^^ expected `usize`, found `G`
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0308, E0435.

View file

@ -4,11 +4,13 @@ trait Foo<const N: Bar<2>> {
//~^ WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//~| ERROR cycle detected when computing type of `Foo::N`
//~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
fn func() {}
}
trait Bar<const M: Foo<2>> {}
//~^ WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
fn main() {}

View file

@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> {
| +++
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:20
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^
@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Bar::M`...
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^^^^^^^^^^
@ -44,6 +44,22 @@ LL | trait Foo<const N: Bar<2>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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: aborting due to 1 previous error; 2 warnings emitted
error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:20
|
LL | trait Foo<const N: Bar<2>> {
| ^^^^^^
|
= note: the only supported types are integers, `bool`, and `char`
error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
|
LL | trait Bar<const M: Foo<2>> {}
| ^^^^^^
|
= note: the only supported types are integers, `bool`, and `char`
error: aborting due to 3 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0391`.