diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index d68c7dd11d1d9..7430fcd70a1f1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -49,7 +49,7 @@ where kind => panic!("expected free alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term(goal, actual); + self.instantiate_normalizes_to_term_with_type_check(goal, actual); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 2f44cc42a5d71..f83099b68cad8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -54,7 +54,7 @@ where .map(|pred| goal.with(cx, pred)), ); - let normalized = match inherent.kind(cx) { + let normalized: I::Term = match inherent.kind(cx) { ty::AliasTermKind::InherentTy { def_id } => { cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into() } @@ -74,7 +74,8 @@ where } kind => panic!("expected inherent alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term(goal, normalized); + + self.instantiate_normalizes_to_term_with_type_check(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index e9a4d7e5919ad..de16d8070c88f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -130,6 +130,28 @@ where .expect("expected goal term to be fully unconstrained"); } + /// Like `instantiate_normalizes_to_term`, but also registers a + /// `ConstArgHasType` goal when the term is a const. This ensures that + /// the const value's type matches the type of the alias it was + /// normalized from, preventing ICEs from type mismatches. + pub fn instantiate_normalizes_to_term_with_type_check( + &mut self, + goal: Goal>, + term: I::Term, + ) { + if let Some(ct) = term.as_const() { + let cx = self.cx(); + let alias = goal.predicate.alias; + let expected_ty = + cx.type_of(alias.def_id()).instantiate(cx, alias.args).skip_norm_wip(); + self.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + self.instantiate_normalizes_to_term(goal, term); + } + /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term /// with a rigid alias. Using this is pretty much always wrong. pub fn structurally_instantiate_normalizes_to_term( @@ -424,7 +446,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term); + ecx.instantiate_normalizes_to_term_with_type_check(goal, term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into) }) } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 84dbd53de83f2..c10c082fc5b1a 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -340,7 +340,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { }), ); self.depth += 1; - let res = if free.kind(infcx.tcx).is_type() { + let res: ty::Term<'tcx> = if free.kind(infcx.tcx).is_type() { infcx .tcx .type_of(free.def_id()) @@ -357,6 +357,19 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { .fold_with(self) .into() }; + // When normalizing a free const alias, register a `ConstArgHasType` + // obligation to ensure the const value's type matches the declared type. + if let Some(ct) = res.as_const() { + let expected_ty = + infcx.tcx.type_of(free.def_id()).instantiate(infcx.tcx, free.args).skip_norm_wip(); + self.obligations.push(Obligation::with_depth( + infcx.tcx, + self.cause.clone(), + self.depth, + self.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } self.depth -= 1; res } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e2458a2392f5f..38501cabe3d15 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -5,6 +5,7 @@ use std::ops::ControlFlow; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; @@ -484,6 +485,30 @@ fn normalize_to_error<'a, 'tcx>( Normalized { value: new_value, obligations } } +/// When normalizing a const alias, register a `ConstArgHasType` obligation +/// to ensure the const value's type matches the declared type. +fn push_const_arg_has_type_obligation<'tcx>( + tcx: TyCtxt<'tcx>, + obligations: &mut PredicateObligations<'tcx>, + cause: &ObligationCause<'tcx>, + depth: usize, + param_env: ty::ParamEnv<'tcx>, + term: Term<'tcx>, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, +) { + if let Some(ct) = term.as_const() { + let expected_ty = tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip(); + obligations.push(Obligation::with_depth( + tcx, + cause.clone(), + depth, + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } +} + /// Confirm and normalize the given inherent projection. // FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] @@ -551,6 +576,17 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() }; + push_const_arg_has_type_obligation( + tcx, + obligations, + &cause, + depth + 1, + param_env, + term, + alias_term.def_id(), + args, + ); + let mut term = selcx.infcx.resolve_vars_if_possible(term); if term.has_aliases() { term = @@ -2046,7 +2082,18 @@ fn confirm_impl_candidate<'cx, 'tcx>( Progress { term: err, obligations: nested } } else { assoc_term_own_obligations(selcx, obligation, &mut nested); - Progress { term: term.instantiate(tcx, args).skip_norm_wip(), obligations: nested } + let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip(); + push_const_arg_has_type_obligation( + tcx, + &mut nested, + &obligation.cause, + obligation.recursion_depth + 1, + obligation.param_env, + instantiated_term, + assoc_term.item.def_id, + args, + ); + Progress { term: instantiated_term, obligations: nested } }; Ok(Projected::Progress(progress)) } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e8c5d10c78ce3..21c6652540bbd 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -5,7 +5,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def::DefKind; -use rustc_infer::traits::PredicateObligations; +use rustc_infer::traits::{Obligation, PredicateObligations}; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ @@ -374,6 +374,18 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { } else { result.normalized_term }; + // When normalizing a const alias, register a `ConstArgHasType` obligation + // to ensure the const value's type matches the declared type. + if let Some(ct) = res.as_const() { + let expected_ty = + tcx.type_of(term.def_id()).instantiate(tcx, term.args).skip_norm_wip(); + self.obligations.push(Obligation::new( + tcx, + self.cause.clone(), + self.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } // `tcx.normalize_canonicalized_projection` may normalize to a type that // still has unevaluated consts, so keep normalizing here if that's the case. // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d3a2c4d20f95d..d41d2cf27f624 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -63,11 +63,11 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { match p.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => false, ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::NormalizesTo(..) | ty::PredicateKind::AliasRelate(..) diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs new file mode 100644 index 0000000000000..906bd5e7ef912 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Zvalidate-mir -Znext-solver + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +type const X: usize = const { N }; +//~^ ERROR type annotations needed + +type const N: usize = "this isn't a usize"; +//~^ ERROR the constant `"this isn't a usize"` is not of type `usize` + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr new file mode 100644 index 0000000000000..0718b739cad0e --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` + --> $DIR/type-const-free-anon-const-mismatch.rs:6:1 + | +LL | type const X: usize = const { N }; + | ^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` + +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-anon-const-mismatch.rs:9:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..a734b4062b2a6 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr @@ -0,0 +1,15 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:13:24 + | +LL | fn f() -> [u8; const { N }] {} + | ^ evaluation of `f::{constant#0}` failed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..2fbd629878bfe --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr @@ -0,0 +1,24 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + | +LL | fn f() -> [u8; const { N }] {} + | ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + | +LL | fn f() -> [u8; const { N }] {} + | - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs new file mode 100644 index 0000000000000..1b66a5d54f7e6 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -0,0 +1,18 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir +//@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte" + +type const N: usize = "this isn't a usize"; +//~^ ERROR the constant `"this isn't a usize"` is not of type `usize` + +fn f() -> [u8; const { N }] {} +//[current]~^ ERROR transmuting from +//[next]~^^ ERROR type annotations needed +//[next]~| ERROR mismatched types [E0308] + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..bf34bcaf9fc9c --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr @@ -0,0 +1,17 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..5d0b81f4a3e0d --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr @@ -0,0 +1,24 @@ +error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs new file mode 100644 index 0000000000000..1f00b4410c4d7 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -0,0 +1,22 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +struct Struct; + +impl Struct { + type const N: usize = "this isn't a usize"; + //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` +} + +fn f() -> [u8; const { Struct::N }] {} +//~^ ERROR mismatched types [E0308] +//[next]~| ERROR type annotations needed + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..7ce0513c91d13 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr @@ -0,0 +1,32 @@ +error[E0053]: method `arr` has an incompatible type for trait + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN } + | +note: type in trait + --> $DIR/type-const-value-type-mismatch.rs:15:5 + | +LL | fn arr() -> [u8; Self::LEN]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn() -> [u8; 0]` + found signature `fn() -> [u8; const { Self::LEN }]` + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..77885cbcfecde --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr @@ -0,0 +1,30 @@ +error[E0271]: type mismatch resolving `::LEN normalizes-to 0` + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0284]: type annotations needed: cannot normalize `::arr::{constant#0}` + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `::arr::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0284, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs new file mode 100644 index 0000000000000..273e7e340fef1 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -0,0 +1,29 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +pub struct A; + +pub trait Array { + type const LEN: usize; + fn arr() -> [u8; Self::LEN]; +} + +impl Array for A { + type const LEN: usize = 0u8; + //~^ ERROR the constant `0` is not of type `usize` + + fn arr() -> [u8; const { Self::LEN }] {} + //~^ ERROR mismatched types [E0308] + //[current]~| ERROR method `arr` has an incompatible type for trait [E0053] + //[next]~| ERROR type annotations needed + //[next]~| ERROR type mismatch resolving `::LEN normalizes-to 0` [E0271] +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index b17a5b2b978a6..74f6aa5a2ddf2 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -5,7 +5,8 @@ type const FREE: u32 = 5_usize; //~^ ERROR the constant `5` is not of type `u32` type const FREE2: isize = FREE; -//~^ ERROR the constant `5` is not of type `isize` +//~^ ERROR the constant `5` is not of type `u32` +//~| ERROR the constant `5` is not of type `isize` trait Tr { type const N: usize; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index e2c916cf6d05a..df728d8065923 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -4,6 +4,12 @@ error: the constant `5` is not of type `u32` LL | type const FREE: u32 = 5_usize; | ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` +error: the constant `5` is not of type `u32` + --> $DIR/type_const-mismatched-types.rs:7:1 + | +LL | type const FREE2: isize = FREE; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` + error: the constant `5` is not of type `isize` --> $DIR/type_const-mismatched-types.rs:7:1 | @@ -11,10 +17,10 @@ LL | type const FREE2: isize = FREE; | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` error: the constant `false` is not of type `usize` - --> $DIR/type_const-mismatched-types.rs:15:5 + --> $DIR/type_const-mismatched-types.rs:16:5 | LL | type const N: usize = false; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors