From e9c273e3775a04c70c0743f24601475de474b64d Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Wed, 18 Mar 2026 11:48:09 +0100 Subject: [PATCH] Always check `ConstArgHasType` even when otherwise ignoring --- .../rustc_hir_analysis/src/check/check.rs | 28 +++- .../rustc_hir_analysis/src/check/wfcheck.rs | 22 ++- .../rustc_trait_selection/src/traits/wf.rs | 43 ++++- ..._const_arg_type_in_free_alias.eager.stderr | 133 +++++++++++++++ ...k_const_arg_type_in_free_alias.lazy.stderr | 151 ++++++++++++++++++ .../check_const_arg_type_in_free_alias.rs | 67 ++++++++ .../check_const_arg_type_in_trait_object.rs | 36 +++++ ...heck_const_arg_type_in_trait_object.stderr | 49 ++++++ 8 files changed, 524 insertions(+), 5 deletions(-) create mode 100644 tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr create mode 100644 tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr create mode 100644 tests/ui/const-generics/check_const_arg_type_in_free_alias.rs create mode 100644 tests/ui/const-generics/check_const_arg_type_in_trait_object.rs create mode 100644 tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 32cfa3003eebe..06ccf61a16203 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -952,10 +952,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); check_type_alias_type_params_are_used(tcx, def_id); + let ty = tcx.type_of(def_id).instantiate_identity(); + let span = tcx.def_span(def_id); if tcx.type_alias_is_lazy(def_id) { res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { - let ty = tcx.type_of(def_id).instantiate_identity(); - let span = tcx.def_span(def_id); let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation( span, @@ -966,6 +966,30 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Ok(()) })); check_variances_for_type_defn(tcx, def_id); + } else { + res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { + // HACK: We sometimes incidentally check that const arguments have the correct + // type as a side effect of the anon const desugaring. To make this "consistent" + // for users we explicitly check `ConstArgHasType` clauses so that const args + // that don't go through an anon const still have their types checked. + // + // We use the unnormalized type as this mirrors the behaviour that we previously + // would have had when all const arguments were anon consts. + // + // Changing this to normalized obligations is a breaking change: + // `type Bar = [(); panic!()];` would become an error + if let Some(unnormalized_obligations) = wfcx.unnormalized_obligations(span, ty) + { + let filtered_obligations = + unnormalized_obligations.into_iter().filter(|o| { + matches!(o.predicate.kind().skip_binder(), + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) + if matches!(ct.kind(), ty::ConstKind::Param(..))) + }); + wfcx.ocx.register_obligations(filtered_obligations) + } + Ok(()) + })); } // Only `Node::Item` and `Node::ForeignItem` still have HIR based diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5656c4566d9ff..18363fa50d20b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -15,6 +15,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{AmbigArg, ItemKind, find_attr}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt}; +use rustc_infer::traits::PredicateObligations; use rustc_lint_defs::builtin::SHADOWING_SUPERTRAIT_ITEMS; use rustc_macros::Diagnostic; use rustc_middle::mir::interpret::ErrorHandled; @@ -124,6 +125,20 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { ty::ClauseKind::WellFormed(term), )); } + + pub(super) fn unnormalized_obligations( + &self, + span: Span, + ty: Ty<'tcx>, + ) -> Option> { + traits::wf::unnormalized_obligations( + self.ocx.infcx, + self.param_env, + ty.into(), + span, + self.body_def_id, + ) + } } pub(super) fn enter_wf_checking_ctxt<'tcx, F>( @@ -140,7 +155,12 @@ where let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env }; - if !tcx.features().trivial_bounds() { + // As of now, bounds are only checked on lazy type aliases, they're ignored for most type + // aliases. So, only check for false global bounds if we're not ignoring bounds altogether. + let ignore_bounds = + tcx.def_kind(body_def_id) == DefKind::TyAlias && !tcx.type_alias_is_lazy(body_def_id); + + if !ignore_bounds && !tcx.features().trivial_bounds() { wfcx.check_false_global_bounds() } f(&mut wfcx)?; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 4a0a99ea27640..b8f5336115e12 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -942,14 +942,53 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // FIXME(#27579) RFC also considers adding trait // obligations that don't refer to Self and // checking those - if let Some(principal) = data.principal_def_id() { + if let Some(principal) = data.principal() { + let principal_def_id = principal.skip_binder().def_id; self.out.push(traits::Obligation::with_depth( tcx, self.cause(ObligationCauseCode::WellFormed(None)), self.recursion_depth, self.param_env, - ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), + ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal_def_id)), )); + + // For the most part we don't add wf predicates corresponding to + // the trait ref's generic arguments which allows code like this + // to compile: + // ```rust + // trait Trait {} + // fn foo(_: &dyn Trait<[u32]>) {} + // ``` + // + // However, we sometimes incidentally check that const arguments + // have the correct type as a side effect of the anon const + // desugaring. To make this "consistent" for users we explicitly + // check `ConstArgHasType` clauses so that const args that don't + // go through an anon const still have their types checked. + // + // See also: https://rustc-dev-guide.rust-lang.org/const-generics.html + let args = principal.skip_binder().with_self_ty(self.tcx(), t).args; + let obligations = + self.nominal_obligations(principal_def_id, args).into_iter().filter(|o| { + let kind = o.predicate.kind().skip_binder(); + match kind { + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + ct, + _, + )) if matches!(ct.kind(), ty::ConstKind::Param(..)) => { + // ConstArgHasType clauses are not higher kinded. Assert as + // such so we can fix this up if that ever changes. + assert!(o.predicate.kind().bound_vars().is_empty()); + // In stable rust, variables from the trait object binder + // cannot be referenced by a ConstArgHasType clause. However, + // under `generic_const_parameter_types`, it can. Ignore those + // predicates for now, to not have HKT-ConstArgHasTypes. + !kind.has_escaping_bound_vars() + } + _ => false, + } + }); + self.out.extend(obligations); } if !t.has_escaping_bound_vars() { diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr b/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr new file mode 100644 index 0000000000000..f62023bd146bb --- /dev/null +++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr @@ -0,0 +1,133 @@ +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:15:1 + | +LL | type ArrLen = [(); B]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:19:1 + | +LL | type ConstArg = Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Foo` + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:32:1 + | +LL | type Alias = <() as IdentityWithUnused>::This; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `IdentityWithUnused` + --> $DIR/check_const_arg_type_in_free_alias.rs:24:26 + | +LL | trait IdentityWithUnused { + | ^^^^^^^^^^^^^^ required by this const generic parameter in `IdentityWithUnused` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:38:1 + | +LL | type UseFree = Free; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:58:1 + | +LL | type IndirectArr = Wrap>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:62:1 + | +LL | type IndirectConstArg = Wrap>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Foo` + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:17:24 + | +LL | type AnonArrLen = [(); true]; + | ^^^^ expected `usize`, found `bool` + | + = note: array length can only be `usize` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:21:25 + | +LL | type AnonConstArg = Foo; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:34:44 + | +LL | type AnonAlias = <() as IdentityWithUnused>::This; + | ^^^^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:40:25 + | +LL | type AnonUseFree = Free; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:37:11 + | +LL | type Free = [(); N]; + | ^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:53:45 + | +LL | type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>; + | ^^^^^^^ expected `bool`, found `usize` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:38:14 + | +LL | type UseFree = Free; + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:60:39 + | +LL | type AnonIndirectArr = Wrap>; + | ^^^^ expected `usize`, found `bool` + | + = note: array length can only be `usize` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:64:43 + | +LL | type AnonIndirectConstArg = Wrap>>; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr b/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr new file mode 100644 index 0000000000000..b9adb4e51e1af --- /dev/null +++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr @@ -0,0 +1,151 @@ +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:15:1 + | +LL | type ArrLen = [(); B]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:17:24 + | +LL | type AnonArrLen = [(); true]; + | ^^^^ expected `usize`, found `bool` + | + = note: array length can only be `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:19:1 + | +LL | type ConstArg = Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Foo` + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:21:25 + | +LL | type AnonConstArg = Foo; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:32:1 + | +LL | type Alias = <() as IdentityWithUnused>::This; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required for `()` to implement `IdentityWithUnused` + --> $DIR/check_const_arg_type_in_free_alias.rs:28:25 + | +LL | impl IdentityWithUnused for T { + | -------------- ^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:34:44 + | +LL | type AnonAlias = <() as IdentityWithUnused>::This; + | ^^^^ expected `usize`, found `bool` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:38:1 + | +LL | type UseFree = Free; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a bound on the type alias `Free` + --> $DIR/check_const_arg_type_in_free_alias.rs:37:11 + | +LL | type Free = [(); N]; + | ^^^^^^^^^^^^^^ required by this bound + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:40:25 + | +LL | type AnonUseFree = Free; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:37:11 + | +LL | type Free = [(); N]; + | ^^^^^^^^^^^^^^ + +error: the constant `N` is not of type `bool` + --> $DIR/check_const_arg_type_in_free_alias.rs:51:1 + | +LL | type UseFreeIndirectlyCorrect = UseFree; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `usize` + | +note: required by a bound on the type alias `UseFree` + --> $DIR/check_const_arg_type_in_free_alias.rs:38:14 + | +LL | type UseFree = Free; + | ^^^^^^^^^^^^^ required by this bound + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:53:45 + | +LL | type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>; + | ^^^^^^^ expected `bool`, found `usize` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:38:14 + | +LL | type UseFree = Free; + | ^^^^^^^^^^^^^ + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:58:1 + | +LL | type IndirectArr = Wrap>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:60:39 + | +LL | type AnonIndirectArr = Wrap>; + | ^^^^ expected `usize`, found `bool` + | + = note: array length can only be `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_free_alias.rs:62:1 + | +LL | type IndirectConstArg = Wrap>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Foo` + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_free_alias.rs:64:43 + | +LL | type AnonIndirectConstArg = Wrap>>; + | ^^^^ expected `usize`, found `bool` + | +note: expected because of the type of the const parameter + --> $DIR/check_const_arg_type_in_free_alias.rs:13:12 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs b/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs new file mode 100644 index 0000000000000..12e277f0c545a --- /dev/null +++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs @@ -0,0 +1,67 @@ +//@ revisions: eager lazy +#![cfg_attr(lazy, feature(lazy_type_alias))] +#![cfg_attr(lazy, expect(incomplete_features))] + +// We currently do not check free type aliases for well formedness. +// However, previously we desugared all const arguments to anon +// consts which resulted in us happening to check that they were +// of the correct type. Nowadays we don't necessarily lower to a +// const argument, but to continue erroring on such code we special +// case `ConstArgHasType` clauses to be checked for free type aliases +// even though we ignore the rest of the wf requirements. + +struct Foo; + +type ArrLen = [(); B]; +//~^ ERROR: the constant `B` is not of type +type AnonArrLen = [(); true]; +//~^ ERROR: mismatched types +type ConstArg = Foo; +//~^ ERROR: the constant `B` is not of type +type AnonConstArg = Foo; +//~^ ERROR: mismatched types + +trait IdentityWithUnused { + type This; +} + +impl IdentityWithUnused for T { + type This = T; +} + +type Alias = <() as IdentityWithUnused>::This; +//~^ ERROR: the constant `B` is not of type +type AnonAlias = <() as IdentityWithUnused>::This; +//~^ ERROR: mismatched types + +type Free = [(); N]; +type UseFree = Free; +//~^ ERROR: the constant `B` is not of type +type AnonUseFree = Free; +//~^ ERROR: mismatched types + +// This previously emitted an error before we stopped using +// anon consts. Now, as free aliases don't exist after ty +// lowering, we don't emit an error because we only see `N` +// being used as an argument to an array length. +// +// Free type aliases are not allowed to have unused generic +// parameters so this shouldn't be able to cause code to +// pass that should error. +type UseFreeIndirectlyCorrect = UseFree; +//[lazy]~^ ERROR: the constant `N` is not of type +type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>; +//~^ ERROR: mismatched types + +struct Wrap(T); + +type IndirectArr = Wrap>; +//~^ ERROR: the constant `B` is not of type +type AnonIndirectArr = Wrap>; +//~^ ERROR: mismatched types +type IndirectConstArg = Wrap>>; +//~^ ERROR: the constant `B` is not of type +type AnonIndirectConstArg = Wrap>>; +//~^ ERROR: mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs b/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs new file mode 100644 index 0000000000000..f5c5350194b7c --- /dev/null +++ b/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs @@ -0,0 +1,36 @@ +// We currently do not check trait objects for well formedness. +// However, previously we desugared all const arguments to anon +// consts which resulted in us happening to check that they were +// of the correct type. Nowadays we don't necessarily lower to a +// const argument, but to continue erroring on such code we special +// case `ConstArgHasType` clauses to be checked for trait objects +// even though we ignore the rest of the wf requirements. + +trait Object {} +trait Object2 {} +trait Object3<'a: 'static, const N: usize> {} + +struct Wrap(T); + +fn arg( + param: &dyn Object, + //~^ ERROR: the constant `B` is not of type + anon: &dyn Object, + //~^ ERROR: mismatched types +) { +} + +fn indirect( + param: &dyn Object2>, + //~^ ERROR: the constant `B` is not of type + anon: &dyn Object2>, + //~^ ERROR: mismatched types +) { +} + +// the 'a: 'static bound should *not* have its error reported (at least, until we implement checking +// all wf things for dyn objects) +fn binder(param: &dyn for<'a> Object3<'a, B>) {} +//~^ ERROR: the constant `B` is not of type + +fn main() {} diff --git a/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr b/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr new file mode 100644 index 0000000000000..4e228f65ab6df --- /dev/null +++ b/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr @@ -0,0 +1,49 @@ +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_trait_object.rs:18:23 + | +LL | anon: &dyn Object, + | ^^^^ expected `usize`, found `bool` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_trait_object.rs:16:12 + | +LL | param: &dyn Object, + | ^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Object` + --> $DIR/check_const_arg_type_in_trait_object.rs:9:14 + | +LL | trait Object {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Object` + +error[E0308]: mismatched types + --> $DIR/check_const_arg_type_in_trait_object.rs:26:34 + | +LL | anon: &dyn Object2>, + | ^^^^ expected `usize`, found `bool` + | + = note: array length can only be `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_trait_object.rs:24:12 + | +LL | param: &dyn Object2>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | + = note: the length of array `[(); B]` must be type `usize` + +error: the constant `B` is not of type `usize` + --> $DIR/check_const_arg_type_in_trait_object.rs:33:33 + | +LL | fn binder(param: &dyn for<'a> Object3<'a, B>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `Object3` + --> $DIR/check_const_arg_type_in_trait_object.rs:11:28 + | +LL | trait Object3<'a: 'static, const N: usize> {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `Object3` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`.