Auto merge of #140553 - BoxyUwU:defer_type_system_ctfe, r=compiler-errors
Defer evaluating type system constants when they use infers or params Split out of #137972, the parts necessary for associated const equality and min generic const args to make progress and have correct semantics around when CTFE is invoked. According to a [previous perf run](https://perf.rust-lang.org/compare.html?start=93257e2d20809d82d1bc0fcc1942480d1a66d7cd&end=01b4cbf0f47c3f782330db88fa5ba199bba1f8a2&stat=instructions:u) of adding the new `const_arg_kind` query we should expect minor regressions here. I think this is acceptable as we should be able to remove this query relatively soon once mgca is more complete as we'll then be able to implement GCE in terms of mgca and rip out `GCEConst` at which point it's trivial to determine what kind of anon const we're dealing with (either it has generics and is a repeat expr hack, or it doesnt and is a normal anon const). This should only affect unstable code as we handle repeat exprs specially and those are the only kinds of type system consts that are allowed to make use of generic parameters. Fixes #133066 Fixes #133199 Fixes #136894 Fixes #137813 r? compiler-errors
This commit is contained in:
commit
52bf0cf795
31 changed files with 552 additions and 195 deletions
|
|
@ -88,6 +88,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
opaque_ty_origin,
|
||||
rendered_precise_capturing_args,
|
||||
const_param_default,
|
||||
anon_const_kind,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
@ -1826,3 +1827,27 @@ fn const_param_default<'tcx>(
|
|||
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
||||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
|
||||
fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||
let const_arg_id = tcx.parent_hir_id(hir_id);
|
||||
match tcx.hir_node(const_arg_id) {
|
||||
hir::Node::ConstArg(_) => {
|
||||
if tcx.features().generic_const_exprs() {
|
||||
ty::AnonConstKind::GCE
|
||||
} else if tcx.features().min_generic_const_args() {
|
||||
ty::AnonConstKind::MCG
|
||||
} else if let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Repeat(_, repeat_count),
|
||||
..
|
||||
}) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
|
||||
&& repeat_count.hir_id == const_arg_id
|
||||
{
|
||||
ty::AnonConstKind::RepeatExprCount
|
||||
} else {
|
||||
ty::AnonConstKind::MCG
|
||||
}
|
||||
}
|
||||
_ => ty::AnonConstKind::NonTypeSystem,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,19 +104,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
}
|
||||
}
|
||||
|
||||
if in_param_ty {
|
||||
// We do not allow generic parameters in anon consts if we are inside
|
||||
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
|
||||
None
|
||||
} else if tcx.features().generic_const_exprs() {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
debug!(?parent_node);
|
||||
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
||||
&& constant.hir_id == hir_id
|
||||
{
|
||||
// enum variant discriminants are not allowed to use any kind of generics
|
||||
None
|
||||
} else if let Some(param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id)
|
||||
match tcx.anon_const_kind(def_id) {
|
||||
// Stable: anon consts are not able to use any generic parameters...
|
||||
ty::AnonConstKind::MCG => None,
|
||||
// we provide generics to repeat expr counts as a backwards compatibility hack. #76200
|
||||
ty::AnonConstKind::RepeatExprCount => Some(parent_did),
|
||||
|
||||
// Even GCE anon const should not be allowed to use generic parameters as it would be
|
||||
// trivially forward declared uses once desugared. E.g. `const N: [u8; ANON::<N>]`.
|
||||
//
|
||||
// We could potentially mirror the hack done for defaults of generic parameters but
|
||||
// this case just doesn't come up much compared to `const N: u32 = ...`. Long term the
|
||||
// hack for defaulted parameters should be removed eventually anyway.
|
||||
ty::AnonConstKind::GCE if in_param_ty => None,
|
||||
// GCE anon consts as a default for a generic parameter should have their provided generics
|
||||
// "truncated" up to whatever generic parameter this anon const is within the default of.
|
||||
//
|
||||
// FIXME(generic_const_exprs): This only handles `const N: usize = /*defid*/` but not type
|
||||
// parameter defaults, e.g. `T = Foo</*defid*/>`.
|
||||
ty::AnonConstKind::GCE
|
||||
if let Some(param_id) =
|
||||
tcx.hir_opt_const_param_default_param_def_id(hir_id) =>
|
||||
{
|
||||
// If the def_id we are calling generics_of on is an anon ct default i.e:
|
||||
//
|
||||
|
|
@ -160,36 +168,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
has_self: generics.has_self,
|
||||
has_late_bound_regions: generics.has_late_bound_regions,
|
||||
};
|
||||
} else {
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
// `feature(generic_const_expressions)` is enabled, so that const expressions
|
||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||
//
|
||||
// Note that we do not supply the parent generics when using
|
||||
// `min_const_generics`.
|
||||
}
|
||||
ty::AnonConstKind::GCE => Some(parent_did),
|
||||
|
||||
// Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/`
|
||||
ty::AnonConstKind::NonTypeSystem
|
||||
if matches!(tcx.parent_hir_node(hir_id), Node::TyPat(_) | Node::Field(_)) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
} else {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
let parent_node = match parent_node {
|
||||
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
|
||||
_ => parent_node,
|
||||
};
|
||||
match parent_node {
|
||||
// HACK(eddyb) this provides the correct generics for repeat
|
||||
// expressions' count (i.e. `N` in `[x; N]`), and explicit
|
||||
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
||||
// as they shouldn't be able to cause query cycle errors.
|
||||
Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
|
||||
if ct.anon_const_hir_id() == Some(hir_id) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
Node::TyPat(_) => Some(parent_did),
|
||||
// Field default values inherit the ADT's generics.
|
||||
Node::Field(_) => Some(parent_did),
|
||||
_ => None,
|
||||
}
|
||||
// Default to no generic parameters for other kinds of anon consts
|
||||
ty::AnonConstKind::NonTypeSystem => None,
|
||||
}
|
||||
}
|
||||
Node::ConstBlock(_)
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
doc_link_traits_in_scope => {
|
||||
tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
|
||||
}
|
||||
anon_const_kind => { table }
|
||||
}
|
||||
|
||||
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||
|
|
|
|||
|
|
@ -1569,6 +1569,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
<- tcx.explicit_implied_const_bounds(def_id).skip_binder());
|
||||
}
|
||||
}
|
||||
if let DefKind::AnonConst = def_kind {
|
||||
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
|
||||
}
|
||||
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
|
||||
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ define_tables! {
|
|||
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
|
||||
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
|
||||
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
|
||||
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ trivial! {
|
|||
rustc_middle::ty::Asyncness,
|
||||
rustc_middle::ty::AsyncDestructor,
|
||||
rustc_middle::ty::BoundVariableKind,
|
||||
rustc_middle::ty::AnonConstKind,
|
||||
rustc_middle::ty::DeducedParamAttrs,
|
||||
rustc_middle::ty::Destructor,
|
||||
rustc_middle::ty::fast_reject::SimplifiedType,
|
||||
|
|
|
|||
|
|
@ -2592,6 +2592,11 @@ rustc_queries! {
|
|||
desc { "estimating codegen size of `{}`", key }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
|
||||
query anon_const_kind(def_id: DefId) -> ty::AnonConstKind {
|
||||
desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) }
|
||||
separate_provide_extern
|
||||
}
|
||||
}
|
||||
|
||||
rustc_with_all_queries! { define_callbacks! }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::MultiSpan;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir::walk::TypeWalker;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
|
||||
|
|
@ -259,3 +259,16 @@ impl<'tcx> Const<'tcx> {
|
|||
TypeWalker::new(self.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum AnonConstKind {
|
||||
/// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope
|
||||
GCE,
|
||||
/// stable `min_const_generics` anon consts are not allowed to use any generic parameters
|
||||
MCG,
|
||||
/// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters
|
||||
/// but must not depend on the actual instantiation. See #76200 for more information
|
||||
RepeatExprCount,
|
||||
/// anon consts outside of the type system, e.g. enum discriminants
|
||||
NonTypeSystem,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ pub use self::closure::{
|
|||
place_to_string_for_capture,
|
||||
};
|
||||
pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind,
|
||||
Value,
|
||||
AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
|
||||
ValTree, ValTreeKind, Value,
|
||||
};
|
||||
pub use self::context::{
|
||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! {
|
|||
ty::AsyncDestructor,
|
||||
ty::AssocItemContainer,
|
||||
ty::Asyncness,
|
||||
ty::AnonConstKind,
|
||||
ty::DeducedParamAttrs,
|
||||
ty::Destructor,
|
||||
ty::Generics,
|
||||
|
|
|
|||
|
|
@ -540,10 +540,13 @@ pub fn try_evaluate_const<'tcx>(
|
|||
| ty::ConstKind::Placeholder(_)
|
||||
| ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers),
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
let opt_anon_const_kind =
|
||||
(tcx.def_kind(uv.def) == DefKind::AnonConst).then(|| tcx.anon_const_kind(uv.def));
|
||||
|
||||
// Postpone evaluation of constants that depend on generic parameters or
|
||||
// inference variables.
|
||||
//
|
||||
// We use `TypingMode::PostAnalysis` here which is not *technically* correct
|
||||
// We use `TypingMode::PostAnalysis` here which is not *technically* correct
|
||||
// to be revealing opaque types here as borrowcheck has not run yet. However,
|
||||
// CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
|
||||
// typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
|
||||
|
|
@ -551,65 +554,95 @@ pub fn try_evaluate_const<'tcx>(
|
|||
//
|
||||
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
|
||||
// instead of having this logic here
|
||||
let (args, typing_env) = if tcx.features().generic_const_exprs()
|
||||
&& uv.has_non_region_infer()
|
||||
{
|
||||
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
|
||||
// inference variables and generic parameters to show up in `ty::Const` even though the anon const
|
||||
// does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
|
||||
match tcx.thir_abstract_const(uv.def) {
|
||||
Ok(Some(ct)) => {
|
||||
let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args));
|
||||
if let Err(e) = ct.error_reported() {
|
||||
return Err(EvaluateConstErr::EvaluationFailure(e));
|
||||
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
|
||||
// If the anon const *does* actually use generic parameters or inference variables from
|
||||
// the generic arguments provided for it, then we should *not* attempt to evaluate it.
|
||||
return Err(EvaluateConstErr::HasGenericsOrInfers);
|
||||
} else {
|
||||
let args = replace_param_and_infer_args_with_placeholder(tcx, uv.args);
|
||||
let typing_env = infcx
|
||||
.typing_env(tcx.erase_regions(param_env))
|
||||
.with_post_analysis_normalized(tcx);
|
||||
(args, typing_env)
|
||||
let (args, typing_env) = match opt_anon_const_kind {
|
||||
// We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system
|
||||
// completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason
|
||||
// about if you have to consider gce whatsoever.
|
||||
Some(ty::AnonConstKind::GCE) => {
|
||||
if uv.has_non_region_infer() || uv.has_non_region_param() {
|
||||
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
|
||||
// inference variables and generic parameters to show up in `ty::Const` even though the anon const
|
||||
// does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
|
||||
match tcx.thir_abstract_const(uv.def) {
|
||||
Ok(Some(ct)) => {
|
||||
let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args));
|
||||
if let Err(e) = ct.error_reported() {
|
||||
return Err(EvaluateConstErr::EvaluationFailure(e));
|
||||
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
|
||||
// If the anon const *does* actually use generic parameters or inference variables from
|
||||
// the generic arguments provided for it, then we should *not* attempt to evaluate it.
|
||||
return Err(EvaluateConstErr::HasGenericsOrInfers);
|
||||
} else {
|
||||
let args =
|
||||
replace_param_and_infer_args_with_placeholder(tcx, uv.args);
|
||||
let typing_env = infcx
|
||||
.typing_env(tcx.erase_regions(param_env))
|
||||
.with_post_analysis_normalized(tcx);
|
||||
(args, typing_env)
|
||||
}
|
||||
}
|
||||
Err(_) | Ok(None) => {
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
|
||||
(args, typing_env)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) | Ok(None) => {
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
|
||||
(args, typing_env)
|
||||
} else {
|
||||
let typing_env = infcx
|
||||
.typing_env(tcx.erase_regions(param_env))
|
||||
.with_post_analysis_normalized(tcx);
|
||||
(uv.args, typing_env)
|
||||
}
|
||||
}
|
||||
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
|
||||
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
|
||||
//
|
||||
// Diagnostics will sometimes replace the identity args of anon consts in
|
||||
// array repeat expr counts with inference variables so we have to handle this
|
||||
// even though it is not something we should ever actually encounter.
|
||||
//
|
||||
// Array repeat expr counts are allowed to syntactically use generic parameters
|
||||
// but must not actually depend on them in order to evalaute successfully. This means
|
||||
// that it is actually fine to evalaute them in their own environment rather than with
|
||||
// the actually provided generic arguments.
|
||||
tcx.dcx().delayed_bug(
|
||||
"Encountered anon const with inference variable args but no error reported",
|
||||
);
|
||||
Some(ty::AnonConstKind::RepeatExprCount) => {
|
||||
if uv.has_non_region_infer() {
|
||||
// Diagnostics will sometimes replace the identity args of anon consts in
|
||||
// array repeat expr counts with inference variables so we have to handle this
|
||||
// even though it is not something we should ever actually encounter.
|
||||
//
|
||||
// Array repeat expr counts are allowed to syntactically use generic parameters
|
||||
// but must not actually depend on them in order to evalaute successfully. This means
|
||||
// that it is actually fine to evalaute them in their own environment rather than with
|
||||
// the actually provided generic arguments.
|
||||
tcx.dcx().delayed_bug("AnonConst with infer args but no error reported");
|
||||
}
|
||||
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
|
||||
(args, typing_env)
|
||||
} else {
|
||||
// FIXME: This codepath is reachable under `associated_const_equality` and in the
|
||||
// future will be reachable by `min_generic_const_args`. We should handle inference
|
||||
// variables and generic parameters properly instead of doing nothing.
|
||||
let typing_env = infcx
|
||||
.typing_env(tcx.erase_regions(param_env))
|
||||
.with_post_analysis_normalized(tcx);
|
||||
(uv.args, typing_env)
|
||||
// The generic args of repeat expr counts under `min_const_generics` are not supposed to
|
||||
// affect evaluation of the constant as this would make it a "truly" generic const arg.
|
||||
// To prevent this we discard all the generic arguments and evalaute with identity args
|
||||
// and in its own environment instead of the current environment we are normalizing in.
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
|
||||
|
||||
(args, typing_env)
|
||||
}
|
||||
_ => {
|
||||
// We are only dealing with "truly" generic/uninferred constants here:
|
||||
// - GCEConsts have been handled separately
|
||||
// - Repeat expr count back compat consts have also been handled separately
|
||||
// So we are free to simply defer evaluation here.
|
||||
//
|
||||
// FIXME: This assumes that `args` are normalized which is not necessarily true
|
||||
//
|
||||
// Const patterns are converted to type system constants before being
|
||||
// evaluated. However, we don't care about them here as pattern evaluation
|
||||
// logic does not go through type system normalization. If it did this would
|
||||
// be a backwards compatibility problem as we do not enforce "syntactic" non-
|
||||
// usage of generic parameters like we do here.
|
||||
if uv.args.has_non_region_param() || uv.args.has_non_region_infer() {
|
||||
return Err(EvaluateConstErr::HasGenericsOrInfers);
|
||||
}
|
||||
|
||||
let typing_env = infcx
|
||||
.typing_env(tcx.erase_regions(param_env))
|
||||
.with_post_analysis_normalized(tcx);
|
||||
(uv.args, typing_env)
|
||||
}
|
||||
};
|
||||
let uv = ty::UnevaluatedConst::new(uv.def, args);
|
||||
|
||||
let uv = ty::UnevaluatedConst::new(uv.def, args);
|
||||
let erased_uv = tcx.erase_regions(uv);
|
||||
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) {
|
||||
Ok(Ok(val)) => Ok(ty::Const::new_value(
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
//@ known-bug: #133199
|
||||
//@ aux-build: aux133199.rs
|
||||
|
||||
extern crate aux133199;
|
||||
|
||||
use aux133199::FixedBitSet;
|
||||
|
||||
fn main() {
|
||||
FixedBitSet::<7>::new();
|
||||
//~^ ERROR
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
//@ known-bug: #136894
|
||||
#![feature(generic_const_exprs)]
|
||||
#![crate_type = "lib"]
|
||||
#![allow(incomplete_features, dead_code)]
|
||||
|
||||
struct X<T>([(); f::<T>()]) where [(); f::<T>()]:;
|
||||
|
||||
const fn f<T>() -> usize { panic!() }
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
//@ known-bug: #137813
|
||||
trait AssocConst {
|
||||
const A: u8;
|
||||
}
|
||||
|
||||
impl<T> AssocConst for (T,) {
|
||||
const A: u8 = 0;
|
||||
}
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
|
||||
fn foo()
|
||||
where
|
||||
(): Trait,
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#![feature(generic_arg_infer, associated_const_equality, generic_const_items)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
// Regression test for #133066 where we would try to evaluate `<() as Foo>::ASSOC<_>` even
|
||||
// though it contained inference variables, which would cause ICEs.
|
||||
|
||||
trait Foo {
|
||||
const ASSOC<const N: u32>: u32;
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
const ASSOC<const N: u32>: u32 = N;
|
||||
}
|
||||
|
||||
fn bar<const N: u32, T: Foo<ASSOC<N> = 10>>() {}
|
||||
|
||||
fn main() {
|
||||
bar::<_, ()>();
|
||||
//~^ ERROR: type mismatch resolving `<() as Foo>::ASSOC<_> == 10`
|
||||
|
||||
// FIXME(mgca):
|
||||
// FIXME(associated_const_equality):
|
||||
// This ought to start compiling once const items are aliases rather than bodies
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
error[E0271]: type mismatch resolving `<() as Foo>::ASSOC<_> == 10`
|
||||
--> $DIR/equality_bound_with_infer.rs:18:14
|
||||
|
|
||||
LL | bar::<_, ()>();
|
||||
| ^^ expected `10`, found `<() as Foo>::ASSOC::<_>`
|
||||
|
|
||||
= note: expected constant `10`
|
||||
found constant `<() as Foo>::ASSOC::<_>`
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/equality_bound_with_infer.rs:15:29
|
||||
|
|
||||
LL | fn bar<const N: u32, T: Foo<ASSOC<N> = 10>>() {}
|
||||
| ^^^^^^^^^^^^^ required by this bound in `bar`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// regression test for #137813 where we would assume all constants in the type system
|
||||
// cannot contain inference variables, even though associated const equality syntax
|
||||
// was still lowered without the feature gate enabled.
|
||||
|
||||
trait AssocConst {
|
||||
const A: u8;
|
||||
}
|
||||
|
||||
impl<T> AssocConst for (T,) {
|
||||
const A: u8 = 0;
|
||||
}
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
//~| ERROR the type parameter `U` is not constrained by the impl trait
|
||||
|
||||
fn foo()
|
||||
where
|
||||
(): Trait,
|
||||
//~^ ERROR type mismatch resolving
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/unconstrained_impl_param.rs:15:45
|
||||
|
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
|
||||
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained_impl_param.rs:15:6
|
||||
|
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0271]: type mismatch resolving `<(_,) as AssocConst>::A == 0`
|
||||
--> $DIR/unconstrained_impl_param.rs:21:5
|
||||
|
|
||||
LL | (): Trait,
|
||||
| ^^^^^^^^^ expected `0`, found `<(_,) as AssocConst>::A`
|
||||
|
|
||||
= note: expected constant `0`
|
||||
found constant `<(_,) as AssocConst>::A`
|
||||
note: required for `()` to implement `Trait`
|
||||
--> $DIR/unconstrained_impl_param.rs:15:9
|
||||
|
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
| ^^^^^ ^^ --------- unsatisfied trait bound introduced here
|
||||
= help: see issue #48214
|
||||
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
|
||||
|
|
||||
LL + #![feature(trivial_bounds)]
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0207, E0271, E0658.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
pub struct FixedBitSet<const N: usize>;
|
||||
pub struct Foo<const N: usize>;
|
||||
|
||||
impl<const N: usize> FixedBitSet<N>
|
||||
impl<const N: usize> Foo<N>
|
||||
where
|
||||
[u8; N.div_ceil(8)]: Sized,
|
||||
{
|
||||
10
tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs
Normal file
10
tests/ui/const-generics/generic_const_exprs/cross-crate-2.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//@ check-pass
|
||||
//@ aux-build: cross-crate-2.rs
|
||||
|
||||
extern crate cross_crate_2;
|
||||
|
||||
use cross_crate_2::Foo;
|
||||
|
||||
fn main() {
|
||||
Foo::<7>::new();
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/dependence_lint.rs:14:32
|
||||
--> $DIR/dependence_lint.rs:15:32
|
||||
|
|
||||
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
@ -8,7 +8,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
|
|||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/dependence_lint.rs:21:37
|
||||
--> $DIR/dependence_lint.rs:22:37
|
||||
|
|
||||
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
@ -27,7 +27,7 @@ LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_
|
|||
= note: `#[warn(const_evaluatable_unchecked)]` on by default
|
||||
|
||||
warning: cannot use constants which depend on generic parameters in types
|
||||
--> $DIR/dependence_lint.rs:17:9
|
||||
--> $DIR/dependence_lint.rs:18:9
|
||||
|
|
||||
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -9,8 +9,19 @@ help: try adding a `where` bound
|
|||
LL | fn foo<T>() where [(); size_of::<*mut T>()]: {
|
||||
| ++++++++++++++++++++++++++++++++
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/dependence_lint.rs:10:5
|
||||
|
|
||||
LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
LL | fn foo<T>() where [(); size_of::<*mut T>()]: {
|
||||
| ++++++++++++++++++++++++++++++++
|
||||
|
||||
error: overly complex generic constant
|
||||
--> $DIR/dependence_lint.rs:17:9
|
||||
--> $DIR/dependence_lint.rs:18:9
|
||||
|
|
||||
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
|
||||
|
|
@ -18,7 +29,7 @@ LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error w
|
|||
= help: consider moving this anonymous constant into a `const` function
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/dependence_lint.rs:14:12
|
||||
--> $DIR/dependence_lint.rs:15:12
|
||||
|
|
||||
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -29,12 +40,12 @@ LL | fn foo<T>() where [(); size_of::<*mut T>()]: {
|
|||
| ++++++++++++++++++++++++++++++++
|
||||
|
||||
error: overly complex generic constant
|
||||
--> $DIR/dependence_lint.rs:21:17
|
||||
--> $DIR/dependence_lint.rs:22:17
|
||||
|
|
||||
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
|
||||
|
|
||||
= help: consider moving this anonymous constant into a `const` function
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use std::mem::size_of;
|
|||
fn foo<T>() {
|
||||
[0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
|
||||
//[gce]~^ ERROR unconstrained
|
||||
//[full]~^^ WARNING cannot use constants
|
||||
//[gce]~| ERROR unconstrained generic constant
|
||||
//[full]~^^^ WARNING cannot use constants
|
||||
//[full]~| WARNING this was previously accepted
|
||||
let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
|
||||
//[full]~^ ERROR generic parameters may not be used
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ error[E0308]: mismatched types
|
|||
--> $DIR/different-fn.rs:10:5
|
||||
|
|
||||
LL | [0; size_of::<Foo<T>>()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `0`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()`
|
||||
|
|
||||
= note: expected constant `size_of::<T>()`
|
||||
found constant `0`
|
||||
found constant `size_of::<Foo<T>>()`
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/different-fn.rs:10:9
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
//@ check-pass
|
||||
|
||||
// regression test for #136894.
|
||||
// I (BoxyUwU) don't know what the underlying cause was here
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![crate_type = "lib"]
|
||||
#![allow(incomplete_features, dead_code)]
|
||||
|
||||
struct X<T>([(); f::<T>()])
|
||||
where
|
||||
[(); f::<T>()]:;
|
||||
|
||||
const fn f<T>() -> usize {
|
||||
panic!()
|
||||
}
|
||||
|
|
@ -25,7 +25,9 @@ impl<T: Copy> DataHolder<T> {
|
|||
}
|
||||
|
||||
<IsCopy<T>>::VALUE
|
||||
} as usize] = []; //~ ERROR unconstrained generic constant
|
||||
} as usize] = [];
|
||||
//~^ ERROR unconstrained generic constant
|
||||
//~^^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -59,5 +59,49 @@ LL + <IsCopy<T>>::VALUE
|
|||
LL ~ } as usize]: = [];
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-71202.rs:28:19
|
||||
|
|
||||
LL | } as usize] = [];
|
||||
| ^^ expected `1 - {
|
||||
trait NotCopy {
|
||||
const VALUE: bool = false;
|
||||
}
|
||||
|
||||
impl<__Type: ?Sized> NotCopy for __Type {}
|
||||
|
||||
struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
|
||||
|
||||
impl<__Type> IsCopy<__Type>
|
||||
where
|
||||
__Type: Sized + Copy,
|
||||
{
|
||||
const VALUE: bool = true;
|
||||
}
|
||||
|
||||
<IsCopy<T>>::VALUE
|
||||
} as usize`, found `0`
|
||||
|
|
||||
= note: expected constant `1 - {
|
||||
trait NotCopy {
|
||||
const VALUE: bool = false;
|
||||
}
|
||||
|
||||
impl<__Type: ?Sized> NotCopy for __Type {}
|
||||
|
||||
struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
|
||||
|
||||
impl<__Type> IsCopy<__Type>
|
||||
where
|
||||
__Type: Sized + Copy,
|
||||
{
|
||||
const VALUE: bool = true;
|
||||
}
|
||||
|
||||
<IsCopy<T>>::VALUE
|
||||
} as usize`
|
||||
found constant `0`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@
|
|||
|
||||
trait TensorDimension {
|
||||
const DIM: usize;
|
||||
//~^ ERROR cycle detected when resolving instance
|
||||
//~| ERROR cycle detected when resolving instance
|
||||
// FIXME Given the current state of the compiler its expected that we cycle here,
|
||||
// but the cycle is still wrong.
|
||||
const ISSCALAR: bool = Self::DIM == 0;
|
||||
fn is_scalar(&self) -> bool {
|
||||
Self::ISSCALAR
|
||||
|
|
@ -49,6 +45,7 @@ impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T
|
|||
|
||||
impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> {
|
||||
fn size(&self) -> [usize; DIM] {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
|
@ -56,12 +53,17 @@ impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T
|
|||
impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> {
|
||||
type Element = T::Element;
|
||||
fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
assert!(DIM >= T::DIM);
|
||||
if !self.inbounds(index) {
|
||||
//~^ ERROR: unconstrained generic constant
|
||||
//~| ERROR: mismatched types
|
||||
return None;
|
||||
}
|
||||
let size = self.size();
|
||||
//~^ ERROR: unconstrained generic constant
|
||||
let newindex: [usize; T::DIM] = Default::default();
|
||||
//~^ ERROR: the trait bound
|
||||
self.reference.bget(newindex)
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +84,8 @@ impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSi
|
|||
fn size(&self) -> [usize; DIM] {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
self.reference.size()
|
||||
//~^ ERROR: unconstrained generic constant
|
||||
//~| ERROR: mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +96,8 @@ impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcas
|
|||
fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
self.reference.bget(index).map(&self.closure)
|
||||
//~^ ERROR: unconstrained generic constant
|
||||
//~| ERROR: mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,12 +106,14 @@ impl<T> TensorDimension for Vec<T> {
|
|||
}
|
||||
impl<T> TensorSize for Vec<T> {
|
||||
fn size(&self) -> [usize; 1] {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
[self.len()]
|
||||
}
|
||||
}
|
||||
impl<T: Clone> Broadcastable for Vec<T> {
|
||||
type Element = T;
|
||||
fn bget(&self, index: [usize; 1]) -> Option<T> {
|
||||
//~^ ERROR: method not compatible with trait
|
||||
self.get(index[0]).cloned()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,5 @@
|
|||
error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`
|
||||
--> $DIR/issue-83765.rs:5:5
|
||||
|
|
||||
LL | const DIM: usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>`...
|
||||
--> $DIR/issue-83765.rs:4:1
|
||||
|
|
||||
LL | trait TensorDimension {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
|
||||
note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:50:1: 50:94>::size` is compatible with trait definition
|
||||
--> $DIR/issue-83765.rs:51:5
|
||||
|
|
||||
LL | fn size(&self) -> [usize; DIM] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`
|
||||
--> $DIR/issue-83765.rs:5:5
|
||||
|
|
||||
LL | const DIM: usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>`...
|
||||
--> $DIR/issue-83765.rs:4:1
|
||||
|
|
||||
LL | trait TensorDimension {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
|
||||
note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:56:1: 56:97>::bget` is compatible with trait definition
|
||||
--> $DIR/issue-83765.rs:58:5
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:82:5
|
||||
--> $DIR/issue-83765.rs:47:5
|
||||
|
|
||||
LL | fn size(&self) -> [usize; DIM] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
@ -46,7 +8,7 @@ LL | fn size(&self) -> [usize; DIM] {
|
|||
found constant `DIM`
|
||||
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:92:5
|
||||
--> $DIR/issue-83765.rs:55:5
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
@ -54,7 +16,145 @@ LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
|||
= note: expected constant `Self::DIM`
|
||||
found constant `DIM`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:84:5
|
||||
|
|
||||
LL | fn size(&self) -> [usize; DIM] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `DIM`
|
||||
|
||||
Some errors have detailed explanations: E0308, E0391.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:96:5
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `DIM`
|
||||
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:108:5
|
||||
|
|
||||
LL | fn size(&self) -> [usize; 1] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `1`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `1`
|
||||
|
||||
error[E0308]: method not compatible with trait
|
||||
--> $DIR/issue-83765.rs:115:5
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; 1]) -> Option<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `1`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `1`
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/issue-83765.rs:58:13
|
||||
|
|
||||
LL | if !self.inbounds(index) {
|
||||
| ^^^^
|
||||
|
|
||||
note: required by a bound in `TensorSize::inbounds`
|
||||
--> $DIR/issue-83765.rs:14:39
|
||||
|
|
||||
LL | fn inbounds(&self, index: [usize; Self::DIM]) -> bool {
|
||||
| ^^^^^^^^^ required by this bound in `TensorSize::inbounds`
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> where [(); Self::DIM]: {
|
||||
| ++++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-83765.rs:58:27
|
||||
|
|
||||
LL | if !self.inbounds(index) {
|
||||
| ^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `DIM`
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/issue-83765.rs:63:25
|
||||
|
|
||||
LL | let size = self.size();
|
||||
| ^^^^
|
||||
|
|
||||
note: required by a bound in `TensorSize::size`
|
||||
--> $DIR/issue-83765.rs:13:31
|
||||
|
|
||||
LL | fn size(&self) -> [usize; Self::DIM];
|
||||
| ^^^^^^^^^ required by this bound in `TensorSize::size`
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> where [(); Self::DIM]: {
|
||||
| ++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `[usize; T::DIM]: Default` is not satisfied
|
||||
--> $DIR/issue-83765.rs:65:41
|
||||
|
|
||||
LL | let newindex: [usize; T::DIM] = Default::default();
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; T::DIM]`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> where [usize; T::DIM]: Default {
|
||||
| ++++++++++++++++++++++++++++++
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/issue-83765.rs:86:24
|
||||
|
|
||||
LL | self.reference.size()
|
||||
| ^^^^
|
||||
|
|
||||
note: required by a bound in `TensorSize::size`
|
||||
--> $DIR/issue-83765.rs:13:31
|
||||
|
|
||||
LL | fn size(&self) -> [usize; Self::DIM];
|
||||
| ^^^^^^^^^ required by this bound in `TensorSize::size`
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
LL | fn size(&self) -> [usize; DIM] where [(); Self::DIM]: {
|
||||
| ++++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-83765.rs:86:9
|
||||
|
|
||||
LL | self.reference.size()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
|
||||
|
|
||||
= note: expected constant `DIM`
|
||||
found constant `Self::DIM`
|
||||
|
||||
error: unconstrained generic constant
|
||||
--> $DIR/issue-83765.rs:98:9
|
||||
|
|
||||
LL | self.reference.bget(index).map(&self.closure)
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `Broadcastable::bget`
|
||||
--> $DIR/issue-83765.rs:21:35
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>;
|
||||
| ^^^^^^^^^ required by this bound in `Broadcastable::bget`
|
||||
help: try adding a `where` bound
|
||||
|
|
||||
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> where [(); Self::DIM]: {
|
||||
| ++++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-83765.rs:98:29
|
||||
|
|
||||
LL | self.reference.bget(index).map(&self.closure)
|
||||
| ^^^^^ expected `Self::DIM`, found `DIM`
|
||||
|
|
||||
= note: expected constant `Self::DIM`
|
||||
found constant `DIM`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
19
tests/ui/pattern/unused-parameters-const-pattern.rs
Normal file
19
tests/ui/pattern/unused-parameters-const-pattern.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//@ check-pass
|
||||
|
||||
// Tests that const patterns that use generic parameters are
|
||||
// allowed if we are still able to evaluate them.
|
||||
|
||||
trait Trait { const ASSOC: usize; }
|
||||
|
||||
impl<T> Trait for T {
|
||||
const ASSOC: usize = 10;
|
||||
}
|
||||
|
||||
fn foo<T>(a: usize) {
|
||||
match a {
|
||||
<T as Trait>::ASSOC => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -62,6 +62,11 @@ LL | / fn foo() -> Bar
|
|||
LL | | where
|
||||
LL | | Bar: Send,
|
||||
| |______________^
|
||||
note: ...which requires computing revealed normalized predicates of `foo::{constant#0}`...
|
||||
--> $DIR/in-where-clause.rs:13:9
|
||||
|
|
||||
LL | [0; 1 + 2]
|
||||
| ^^^^^
|
||||
= note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(<Bar as core::marker::Send>, polarity:Positive), bound_vars: [] }]`...
|
||||
note: ...which requires computing type of `Bar::{opaque#0}`...
|
||||
--> $DIR/in-where-clause.rs:5:12
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue