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 16a86cc44ccf9..85d079e84073e 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 { + let normalized: I::Term = match inherent.kind { ty::AliasTermKind::InherentTy { def_id } => { cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into() } @@ -74,6 +74,7 @@ where } kind => panic!("expected inherent alias, found {kind:?}"), }; + self.instantiate_normalizes_to_term(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 d35e05aa33cf2..a3be35ca6e61f 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 @@ -121,11 +121,37 @@ where /// We know `term` to always be a fully unconstrained inference variable, so /// `eq` should never fail here. However, in case `term` contains aliases, we /// emit nested `AliasRelate` goals to structurally normalize the alias. + /// + /// Additionally, when `term` is a const, this registers a `ConstArgHasType` + /// goal to ensure that the const value's type matches the declared type of + /// the alias it was normalized from. + /// + /// You may reasonably wonder: shouldn't `wfcheck::check_type_const` already + /// catch any such type mismatch at the definition site, so that the + /// definition is tainted and we never even attempt to normalize a reference + /// to it? In principle that's exactly what should happen. + /// However, when CTFE runs on a MIR body, normalizing a type const within + /// that body can change the type of the resulting value, causing the MIR + /// to become ill-formed. If `check_type_const` for that alias has not yet + /// reported its error, no prior error has been recorded and MIR validation + /// fires a `span_bug!`. Registering the obligation here ensures the type + /// mismatch is reported during normalization itself, tainting the MIR + /// before validation runs. pub fn instantiate_normalizes_to_term( &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.eq(goal.param_env, goal.predicate.term, term) .expect("expected goal term to be fully unconstrained"); } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index d3bad276d5688..22ef6faf96aed 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { }), ); self.depth += 1; - let res = if free.kind.is_type() { + let res: ty::Term<'tcx> = if free.kind.is_type() { infcx .tcx .type_of(free.def_id()) @@ -356,6 +356,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 e392ca6fa2cf9..d149911a92de5 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; @@ -487,6 +488,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))] @@ -554,6 +579,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 = @@ -2049,7 +2085,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_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 96586713aed6f..1505fd20bbdb1 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -2,7 +2,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; -use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; +use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::normalize::NormalizationResult; @@ -19,6 +19,25 @@ pub(crate) fn provide(p: &mut Providers) { }; } +/// If `normalized_term` is a const, returns a `ConstArgHasType` obligation +/// to verify that the const value's type matches the alias's declared type. +/// Returns `None` if the term is a type rather than a const. +fn const_arg_has_type_obligation<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + normalized_term: ty::Term<'tcx>, + goal: ty::AliasTerm<'tcx>, +) -> Option> { + let ct = normalized_term.as_const()?; + let expected_ty = tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip(); + Some(traits::Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )) +} + fn normalize_canonicalized_projection<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalAliasGoal<'tcx>, @@ -40,6 +59,12 @@ fn normalize_canonicalized_projection<'tcx>( 0, &mut obligations, ); + obligations.extend(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); ocx.register_obligations(obligations); // #112047: With projections and opaques, we are able to create opaques that // are recursive (given some generic parameters of the opaque's type variables). @@ -86,11 +111,17 @@ fn normalize_canonicalized_free_alias<'tcx>( }, ); ocx.register_obligations(obligations); - let normalized_term = if goal.kind.is_type() { + let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() { tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() } else { tcx.const_of_item(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() }; + ocx.register_obligations(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); Ok(NormalizationResult { normalized_term }) }, ) @@ -116,6 +147,12 @@ fn normalize_canonicalized_inherent_projection<'tcx>( 0, &mut obligations, ); + obligations.extend(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); ocx.register_obligations(obligations); Ok(NormalizationResult { normalized_term }) 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..8ce226a564b0f --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-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-free-value-type-mismatch.rs:9:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-free-value-type-mismatch.rs:12:11 + | +LL | fn f() -> [u8; const { N }] {} + | - ^^^^^^^^^^^^^^^^^ expected `[u8; const { 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-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..c69455b82dd42 --- /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:9: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:12:11 + | +LL | fn f() -> [u8; const { N }] {} + | ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-free-value-type-mismatch.rs:12: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..ad2e584f34938 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -0,0 +1,17 @@ +#![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 + +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 mismatched types [E0308] +//[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