mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Always check ConstArgHasType even when otherwise ignoring
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
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 @@ pub(super) fn register_wf_obligation(
|
||||
ty::ClauseKind::WellFormed(term),
|
||||
));
|
||||
}
|
||||
|
||||
pub(super) fn unnormalized_obligations(
|
||||
&self,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<PredicateObligations<'tcx>> {
|
||||
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 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
||||
|
||||
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)?;
|
||||
|
||||
@@ -942,14 +942,53 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
// 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<T: Sized> {}
|
||||
// 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() {
|
||||
|
||||
@@ -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<const B: bool> = [(); 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<const B: bool> = Foo<B>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^ 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<const B: bool> = <() as IdentityWithUnused<B>>::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<const N: usize> {
|
||||
| ^^^^^^^^^^^^^^ 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<const B: bool> = Free<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:58:1
|
||||
|
|
||||
LL | type IndirectArr<const B: bool> = Wrap<Wrap<[(); 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:62:1
|
||||
|
|
||||
LL | type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^ 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<true>;
|
||||
| ^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:34:44
|
||||
|
|
||||
LL | type AnonAlias = <() as IdentityWithUnused<true>>::This;
|
||||
| ^^^^ expected `usize`, found `bool`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:40:25
|
||||
|
|
||||
LL | type AnonUseFree = Free<true>;
|
||||
| ^^^^ 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<const N: usize> = [(); 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<const B: bool> = Free<B>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:60:39
|
||||
|
|
||||
LL | type AnonIndirectArr = Wrap<Wrap<[(); 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:64:43
|
||||
|
|
||||
LL | type AnonIndirectConstArg = Wrap<Wrap<Foo<true>>>;
|
||||
| ^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
@@ -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<const B: bool> = [(); 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<const B: bool> = Foo<B>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^ 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<true>;
|
||||
| ^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: the constant `B` is not of type `usize`
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:32:1
|
||||
|
|
||||
LL | type Alias<const B: bool> = <() as IdentityWithUnused<B>>::This;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
|
||||
note: required for `()` to implement `IdentityWithUnused<B>`
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:28:25
|
||||
|
|
||||
LL | impl<T, const N: usize> IdentityWithUnused<N> 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<true>>::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<const B: bool> = Free<B>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize> = [(); N];
|
||||
| ^^^^^^^^^^^^^^ required by this bound
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:40:25
|
||||
|
|
||||
LL | type AnonUseFree = Free<true>;
|
||||
| ^^^^ 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<const N: usize> = [(); N];
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: the constant `N` is not of type `bool`
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:51:1
|
||||
|
|
||||
LL | type UseFreeIndirectlyCorrect<const N: usize> = UseFree<N>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const B: bool> = Free<B>;
|
||||
| ^^^^^^^^^^^^^ 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<const B: bool> = Free<B>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: the constant `B` is not of type `usize`
|
||||
--> $DIR/check_const_arg_type_in_free_alias.rs:58:1
|
||||
|
|
||||
LL | type IndirectArr<const B: bool> = Wrap<Wrap<[(); 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:60:39
|
||||
|
|
||||
LL | type AnonIndirectArr = Wrap<Wrap<[(); 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:62:1
|
||||
|
|
||||
LL | type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^ 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<Wrap<Foo<true>>>;
|
||||
| ^^^^ 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<const N: usize>;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
@@ -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<const N: usize>;
|
||||
|
||||
type ArrLen<const B: bool> = [(); B];
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonArrLen = [(); true];
|
||||
//~^ ERROR: mismatched types
|
||||
type ConstArg<const B: bool> = Foo<B>;
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonConstArg = Foo<true>;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
trait IdentityWithUnused<const N: usize> {
|
||||
type This;
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IdentityWithUnused<N> for T {
|
||||
type This = T;
|
||||
}
|
||||
|
||||
type Alias<const B: bool> = <() as IdentityWithUnused<B>>::This;
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonAlias = <() as IdentityWithUnused<true>>::This;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
type Free<const N: usize> = [(); N];
|
||||
type UseFree<const B: bool> = Free<B>;
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonUseFree = Free<true>;
|
||||
//~^ 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<const N: usize> = UseFree<N>;
|
||||
//[lazy]~^ ERROR: the constant `N` is not of type
|
||||
type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
struct Wrap<T>(T);
|
||||
|
||||
type IndirectArr<const B: bool> = Wrap<Wrap<[(); B]>>;
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonIndirectArr = Wrap<Wrap<[(); true]>>;
|
||||
//~^ ERROR: mismatched types
|
||||
type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
type AnonIndirectConstArg = Wrap<Wrap<Foo<true>>>;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
fn main() {}
|
||||
@@ -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<const N: usize> {}
|
||||
trait Object2<T> {}
|
||||
trait Object3<'a: 'static, const N: usize> {}
|
||||
|
||||
struct Wrap<T>(T);
|
||||
|
||||
fn arg<const B: bool, const N: usize>(
|
||||
param: &dyn Object<B>,
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
anon: &dyn Object<true>,
|
||||
//~^ ERROR: mismatched types
|
||||
) {
|
||||
}
|
||||
|
||||
fn indirect<const B: bool, const N: usize>(
|
||||
param: &dyn Object2<Wrap<[(); B]>>,
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
anon: &dyn Object2<Wrap<[(); true]>>,
|
||||
//~^ 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<const B: bool>(param: &dyn for<'a> Object3<'a, B>) {}
|
||||
//~^ ERROR: the constant `B` is not of type
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,49 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/check_const_arg_type_in_trait_object.rs:18:23
|
||||
|
|
||||
LL | anon: &dyn Object<true>,
|
||||
| ^^^^ 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<B>,
|
||||
| ^^^^^^^^^^^^^^ 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<const N: usize> {}
|
||||
| ^^^^^^^^^^^^^^ 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<Wrap<[(); 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_trait_object.rs:24:12
|
||||
|
|
||||
LL | param: &dyn Object2<Wrap<[(); 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_trait_object.rs:33:33
|
||||
|
|
||||
LL | fn binder<const B: bool>(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`.
|
||||
Reference in New Issue
Block a user